summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Welsh <contact@evanwelsh.com>2021-09-17 23:48:04 -0700
committerEvan Welsh <contact@evanwelsh.com>2021-09-23 18:26:20 -0700
commit91d6953ee6bc25aee662abeb2a6c4162245fef72 (patch)
tree88ba981dba34fdd68a4fb9cddee7c950bc1ca10c
parentff88b5ab91452d5f36b5ddb622ebac54d205b959 (diff)
downloadgnome-shell-ewlsh/esm.tar.gz
ESM Part 1ewlsh/esm
-rw-r--r--HACKING.md4
-rw-r--r--js/gdm/authPrompt.js47
-rw-r--r--js/gdm/batch.js14
-rw-r--r--js/gdm/credentialManager.js4
-rw-r--r--js/gdm/loginDialog.js51
-rw-r--r--js/gdm/oVirt.js12
-rw-r--r--js/gdm/realmd.js8
-rw-r--r--js/gdm/util.js63
-rw-r--r--js/gdm/vmware.js12
-rw-r--r--js/js-resources.gresource.xml3
-rw-r--r--js/misc/config.d.ts19
-rw-r--r--js/misc/config.js.in2
-rw-r--r--js/misc/extensionUtils.js96
-rw-r--r--js/misc/fileUtilsModule.js117
-rw-r--r--js/misc/gnomeSession.js17
-rw-r--r--js/misc/history.js16
-rw-r--r--js/misc/ibusManager.js15
-rw-r--r--js/misc/inputMethod.js12
-rw-r--r--js/misc/introspect.js13
-rw-r--r--js/misc/jsParse.js13
-rw-r--r--js/misc/keyboardManager.js23
-rw-r--r--js/misc/loginManager.js20
-rw-r--r--js/misc/modemManager.js19
-rw-r--r--js/misc/objectManager.js10
-rw-r--r--js/misc/params.d.ts6
-rw-r--r--js/misc/params.js2
-rw-r--r--js/misc/parentalControlsManager.js17
-rw-r--r--js/misc/permissionStore.js6
-rw-r--r--js/misc/signals.d.ts9
-rw-r--r--js/misc/signals.js3
-rw-r--r--js/misc/smartcardManager.js12
-rw-r--r--js/misc/systemActions.js21
-rw-r--r--js/misc/util.js65
-rw-r--r--js/misc/weather.js19
-rw-r--r--js/perf/basic.js11
-rw-r--r--js/perf/core.js8
-rw-r--r--js/perf/hwtest.js11
-rw-r--r--js/ui/accessDialog.js24
-rw-r--r--js/ui/altTab.js80
-rw-r--r--js/ui/animation.js43
-rw-r--r--js/ui/appDisplay.js213
-rw-r--r--js/ui/appFavorites.js12
-rw-r--r--js/ui/appMenu.js10
-rw-r--r--js/ui/audioDeviceSelection.js29
-rw-r--r--js/ui/background.js90
-rw-r--r--js/ui/backgroundMenu.js13
-rw-r--r--js/ui/barLevel.js11
-rw-r--r--js/ui/boxpointer.js28
-rw-r--r--js/ui/calendar.js66
-rw-r--r--js/ui/checkBox.js9
-rw-r--r--js/ui/closeDialog.js35
-rw-r--r--js/ui/components.js (renamed from js/ui/components/__init__.js)22
-rw-r--r--js/ui/components/automountManager.js31
-rw-r--r--js/ui/components/autorunManager.js58
-rw-r--r--js/ui/components/keyring.js31
-rw-r--r--js/ui/components/networkAgent.js49
-rw-r--r--js/ui/components/polkitAgent.js41
-rw-r--r--js/ui/components/telepathyClient.js220
-rw-r--r--js/ui/ctrlAltTab.js20
-rw-r--r--js/ui/dash.js97
-rw-r--r--js/ui/dateMenu.js73
-rw-r--r--js/ui/dialog.js29
-rw-r--r--js/ui/dnd.js95
-rw-r--r--js/ui/edgeDragAction.js17
-rw-r--r--js/ui/endSessionDialog.js60
-rw-r--r--js/ui/environment.js686
-rw-r--r--js/ui/extensionDownloader.js28
-rw-r--r--js/ui/extensionSystem.js69
-rw-r--r--js/ui/focusCaretTracker.js6
-rw-r--r--js/ui/grabHelper.js10
-rw-r--r--js/ui/ibusCandidatePopup.js27
-rw-r--r--js/ui/iconGrid.js175
-rw-r--r--js/ui/inhibitShortcutsDialog.js27
-rw-r--r--js/ui/init.js14
-rw-r--r--js/ui/kbdA11yDialog.js26
-rw-r--r--js/ui/keyboard.js81
-rw-r--r--js/ui/layout.js91
-rw-r--r--js/ui/lightbox.js15
-rw-r--r--js/ui/locatePointer.js8
-rw-r--r--js/ui/lookingGlass.js86
-rw-r--r--js/ui/magnifier.js115
-rw-r--r--js/ui/main.js1493
-rw-r--r--js/ui/messageList.js59
-rw-r--r--js/ui/messageTray.js94
-rw-r--r--js/ui/modalDialog.js43
-rw-r--r--js/ui/mpris.js22
-rw-r--r--js/ui/notificationDaemon.js55
-rw-r--r--js/ui/osdMonitorLabeler.js13
-rw-r--r--js/ui/osdWindow.js24
-rw-r--r--js/ui/overview.js41
-rw-r--r--js/ui/overviewControls.js60
-rw-r--r--js/ui/padOsd.js65
-rw-r--r--js/ui/pageIndicators.js10
-rw-r--r--js/ui/panel.js140
-rw-r--r--js/ui/panelMenu.js25
-rw-r--r--js/ui/pointerA11yTimeout.js15
-rw-r--r--js/ui/pointerWatcher.js10
-rw-r--r--js/ui/popupMenu.js119
-rw-r--r--js/ui/remoteSearch.js23
-rw-r--r--js/ui/ripples.js5
-rw-r--r--js/ui/runDialog.js26
-rw-r--r--js/ui/screenShield.js48
-rw-r--r--js/ui/screenshot.js45
-rw-r--r--js/ui/scripting.js56
-rw-r--r--js/ui/search.js75
-rw-r--r--js/ui/searchController.js15
-rw-r--r--js/ui/sessionMode.js21
-rw-r--r--js/ui/shellDBus.js48
-rw-r--r--js/ui/shellEntry.js19
-rw-r--r--js/ui/shellMountOperation.js62
-rw-r--r--js/ui/slider.js11
-rw-r--r--js/ui/status/accessibility.js18
-rw-r--r--js/ui/status/bluetooth.js42
-rw-r--r--js/ui/status/brightness.js14
-rw-r--r--js/ui/status/dwellClick.js10
-rw-r--r--js/ui/status/keyboard.js102
-rw-r--r--js/ui/status/location.js39
-rw-r--r--js/ui/status/network.js123
-rw-r--r--js/ui/status/nightLight.js13
-rw-r--r--js/ui/status/power.js16
-rw-r--r--js/ui/status/powerProfiles.js10
-rw-r--r--js/ui/status/remoteAccess.js9
-rw-r--r--js/ui/status/rfkill.js17
-rw-r--r--js/ui/status/system.js18
-rw-r--r--js/ui/status/thunderbolt.js30
-rw-r--r--js/ui/status/volume.js31
-rw-r--r--js/ui/swipeTracker.js38
-rw-r--r--js/ui/switchMonitor.js19
-rw-r--r--js/ui/switcherPopup.js36
-rw-r--r--js/ui/unlockDialog.js46
-rw-r--r--js/ui/userWidget.js33
-rw-r--r--js/ui/welcomeDialog.js19
-rw-r--r--js/ui/windowAttentionHandler.js29
-rw-r--r--js/ui/windowManager.js122
-rw-r--r--js/ui/windowMenu.js15
-rw-r--r--js/ui/windowPreview.js43
-rw-r--r--js/ui/workspace.js53
-rw-r--r--js/ui/workspaceAnimation.js17
-rw-r--r--js/ui/workspaceSwitcherPopup.js20
-rw-r--r--js/ui/workspaceThumbnail.js72
-rw-r--r--js/ui/workspacesView.js47
-rw-r--r--js/ui/xdndHandler.js13
-rw-r--r--src/main.c4
-rw-r--r--tests/interactive/background-repeat.js4
-rw-r--r--tests/interactive/background-size.js6
-rw-r--r--tests/interactive/border-radius.js4
-rw-r--r--tests/interactive/border-width.js4
-rw-r--r--tests/interactive/borders.js3
-rw-r--r--tests/interactive/box-layout.js4
-rw-r--r--tests/interactive/box-shadow-animated.js7
-rw-r--r--tests/interactive/box-shadows.js3
-rw-r--r--tests/interactive/calendar.js4
-rw-r--r--tests/interactive/css-fonts.js4
-rw-r--r--tests/interactive/entry.js5
-rwxr-xr-xtests/interactive/gapplication.js10
-rw-r--r--tests/interactive/icons.js4
-rw-r--r--tests/interactive/inline-style.js4
-rw-r--r--tests/interactive/scroll-view-sizing.js11
-rw-r--r--tests/interactive/scrolling.js5
-rwxr-xr-xtests/interactive/test-title.js5
-rw-r--r--tests/interactive/transitions.js3
-rw-r--r--tests/testcommon/ui.js12
-rw-r--r--tests/unit/markup.js3
163 files changed, 4826 insertions, 2909 deletions
diff --git a/HACKING.md b/HACKING.md
index bdcb9ba93..612b7fdba 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -66,7 +66,7 @@ library. These headers are not installed, distributed or introspected.
Use UpperCamelCase when importing modules to distinguish them from ordinary
variables, e.g.
```javascript
- const GLib = imports.gi.GLib;
+ import GLib from 'gi://GLib';
```
Imports should be categorized into one of two places. The top-most import block
should contain only "environment imports". These are either modules from
@@ -118,7 +118,7 @@ See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/N
There are many approaches to classes in JavaScript. We use standard ES6 classes
whenever possible, that is when not inheriting from GObjects.
```javascript
- var IconLabelMenuItem = class extends PopupMenu.PopupMenuBaseItem {
+ export class IconLabelMenuItem extends PopupMenu.PopupMenuBaseItem {
constructor(icon, label) {
super({ reactive: false });
this.actor.add_child(icon);
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index d4edfb9ef..b67d5b590 100644
--- a/js/gdm/authPrompt.js
+++ b/js/gdm/authPrompt.js
@@ -1,29 +1,34 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AuthPrompt */
-const { Clutter, GLib, GObject, Pango, Shell, St } = imports.gi;
+const { Clutter, GLib, GObject, Pango, Shell } = imports.gi;
-const Animation = imports.ui.animation;
-const Batch = imports.gdm.batch;
-const GdmUtil = imports.gdm.util;
-const OVirt = imports.gdm.oVirt;
-const Vmware = imports.gdm.vmware;
-const ShellEntry = imports.ui.shellEntry;
-const UserWidget = imports.ui.userWidget;
-const Util = imports.misc.util;
+import St from 'gi://St';
+import Gdm from 'gi://Gdm';
-var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
-var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000;
-var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
+import * as Animation from '../ui/animation.js';
+import * as Batch from './batch.js';
+import * as GdmUtil from './util.js';
+import * as OVirt from './oVirt.js';
+import * as Vmware from './vmware.js';
+import * as ShellEntry from '../ui/shellEntry.js';
+import * as UserWidget from '../ui/userWidget.js';
+import * as Util from '../misc/util.js';
-var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
+export let DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
+export let DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000;
+export let DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
-var AuthPromptMode = {
+export let MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
+
+/** @enum {number} */
+export const AuthPromptMode = {
UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1,
};
-var AuthPromptStatus = {
+/** @enum {number} */
+export const AuthPromptStatus = {
NOT_VERIFYING: 0,
VERIFYING: 1,
VERIFICATION_FAILED: 2,
@@ -32,13 +37,14 @@ var AuthPromptStatus = {
VERIFICATION_IN_PROGRESS: 5,
};
-var BeginRequestType = {
+/** @enum {number} */
+export const BeginRequestType = {
PROVIDE_USERNAME: 0,
DONT_PROVIDE_USERNAME: 1,
REUSE_USERNAME: 2,
};
-var AuthPrompt = GObject.registerClass({
+export const AuthPrompt = GObject.registerClass({
Signals: {
'cancelled': {},
'failed': {},
@@ -47,6 +53,10 @@ var AuthPrompt = GObject.registerClass({
'reset': { param_types: [GObject.TYPE_UINT] },
},
}, class AuthPrompt extends St.BoxLayout {
+ /**
+ * @param {Gdm.Client} gdmClient
+ * @param {AuthPromptMode} mode
+ */
_init(gdmClient, mode) {
super._init({
style_class: 'login-dialog-prompt-layout',
@@ -583,6 +593,9 @@ var AuthPrompt = GObject.registerClass({
this._entry.clutter_text.insert_unichar(unichar);
}
+ /**
+ * @param {{ userName?: string | null, hold?: Batch.Hold | null }} [params]
+ */
begin(params = {}) {
let { userName = null, hold = null } = params;
diff --git a/js/gdm/batch.js b/js/gdm/batch.js
index f841f0f8e..901e0d11a 100644
--- a/js/gdm/batch.js
+++ b/js/gdm/batch.js
@@ -45,10 +45,10 @@
*/
/* exported ConcurrentBatch, ConsecutiveBatch */
-const { GObject } = imports.gi;
-const Signals = imports.misc.signals;
+import GObject from 'gi://GObject';
+import * as Signals from '../misc/signals.js';
-var Task = class extends Signals.EventEmitter {
+export class Task extends Signals.EventEmitter {
constructor(scope, handler) {
super();
@@ -68,7 +68,7 @@ var Task = class extends Signals.EventEmitter {
}
};
-var Hold = class extends Task {
+export class Hold extends Task {
constructor() {
super(null, () => this);
@@ -104,7 +104,7 @@ var Hold = class extends Task {
}
};
-var Batch = class extends Task {
+export class Batch extends Task {
constructor(scope, tasks) {
super();
@@ -173,7 +173,7 @@ var Batch = class extends Task {
}
};
-var ConcurrentBatch = class extends Batch {
+export class ConcurrentBatch extends Batch {
process() {
let hold = this.runTask();
@@ -187,7 +187,7 @@ var ConcurrentBatch = class extends Batch {
}
};
-var ConsecutiveBatch = class extends Batch {
+export class ConsecutiveBatch extends Batch {
process() {
let hold = this.runTask();
diff --git a/js/gdm/credentialManager.js b/js/gdm/credentialManager.js
index c53de11df..53bb2ded0 100644
--- a/js/gdm/credentialManager.js
+++ b/js/gdm/credentialManager.js
@@ -1,9 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CredentialManager */
-const Signals = imports.misc.signals;
+import * as Signals from "../misc/signals.js";
-var CredentialManager = class CredentialManager extends Signals.EventEmitter {
+export class CredentialManager extends Signals.EventEmitter {
constructor(service) {
super();
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 760d7e9ef..3eb8e41db 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -17,28 +17,40 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-const { AccountsService, Atk, Clutter, Gdm, Gio,
- GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
-
-const AuthPrompt = imports.gdm.authPrompt;
-const Batch = imports.gdm.batch;
-const BoxPointer = imports.ui.boxpointer;
-const CtrlAltTab = imports.ui.ctrlAltTab;
-const GdmUtil = imports.gdm.util;
-const Layout = imports.ui.layout;
-const LoginManager = imports.misc.loginManager;
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
-const Realmd = imports.gdm.realmd;
-const UserWidget = imports.ui.userWidget;
+import AccountsService from 'gi://AccountsService';
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import Gdm from 'gi://Gdm';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AuthPrompt from './authPrompt.js';
+import * as Batch from './batch.js';
+import * as BoxPointer from '../ui/boxpointer.js';
+import * as CtrlAltTab from '../ui/ctrlAltTab.js';
+import * as GdmUtil from './util.js';
+import * as Layout from '../ui/layout.js';
+import * as LoginManager from "../misc/loginManager.js";
+import Main from '../ui/main.js';
+import * as PopupMenu from '../ui/popupMenu.js';
+import * as Realmd from './realmd.js';
+import * as UserWidget from '../ui/userWidget.js';
const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
-var UserListItem = GObject.registerClass({
+export const UserListItem = GObject.registerClass({
Signals: { 'activate': {} },
}, class UserListItem extends St.Button {
+ /**
+ * @param {AccountsService.User} user
+ */
_init(user) {
let layout = new St.BoxLayout({
vertical: true,
@@ -152,7 +164,7 @@ var UserListItem = GObject.registerClass({
}
});
-var UserList = GObject.registerClass({
+export const UserList = GObject.registerClass({
Signals: {
'activate': { param_types: [UserListItem.$gtype] },
'item-added': { param_types: [UserListItem.$gtype] },
@@ -304,7 +316,7 @@ var UserList = GObject.registerClass({
}
});
-var SessionMenuButton = GObject.registerClass({
+export const SessionMenuButton = GObject.registerClass({
Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } },
}, class SessionMenuButton extends St.Bin {
_init() {
@@ -400,12 +412,15 @@ var SessionMenuButton = GObject.registerClass({
}
});
-var LoginDialog = GObject.registerClass({
+export const LoginDialog = GObject.registerClass({
Signals: {
'failed': {},
'wake-up-screen': {},
},
}, class LoginDialog extends St.Widget {
+ /**
+ * @param {Clutter.Actor} parentActor
+ */
_init(parentActor) {
super._init({ style_class: 'login-dialog', visible: false });
diff --git a/js/gdm/oVirt.js b/js/gdm/oVirt.js
index 4cf17d99e..6e9a5211f 100644
--- a/js/gdm/oVirt.js
+++ b/js/gdm/oVirt.js
@@ -1,10 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported getOVirtCredentialsManager */
-const Gio = imports.gi.Gio;
-const Credential = imports.gdm.credentialManager;
+import Gio from 'gi://Gio';
+import * as Credential from './credentialManager.js';
-var SERVICE_NAME = 'gdm-ovirtcred';
+export const SERVICE_NAME = 'gdm-ovirtcred';
const OVirtCredentialsIface = `
<node>
@@ -17,6 +16,7 @@ const OVirtCredentialsIface = `
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);
+/** @type {OVirtCredentialsManager | null} */
let _oVirtCredentialsManager = null;
function OVirtCredentials() {
@@ -30,7 +30,7 @@ function OVirtCredentials() {
return self;
}
-var OVirtCredentialsManager = class OVirtCredentialsManager extends Credential.CredentialManager {
+export class OVirtCredentialsManager extends Credential.CredentialManager {
constructor() {
super(SERVICE_NAME);
this._credentials = OVirtCredentials();
@@ -41,7 +41,7 @@ var OVirtCredentialsManager = class OVirtCredentialsManager extends Credential.C
}
};
-function getOVirtCredentialsManager() {
+export function getOVirtCredentialsManager() {
if (!_oVirtCredentialsManager)
_oVirtCredentialsManager = new OVirtCredentialsManager();
diff --git a/js/gdm/realmd.js b/js/gdm/realmd.js
index b7ff5ad54..44335b3dc 100644
--- a/js/gdm/realmd.js
+++ b/js/gdm/realmd.js
@@ -1,10 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Manager */
-const Gio = imports.gi.Gio;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import * as Signals from '../misc/signals.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const ProviderIface = loadInterfaceXML("org.freedesktop.realmd.Provider");
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
@@ -15,7 +15,7 @@ const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
-var Manager = class extends Signals.EventEmitter {
+export class Manager extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/gdm/util.js b/js/gdm/util.js
index 0adb22add..7f4f2715c 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -3,15 +3,18 @@
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor,
ShellUserVerifier */
-const { Clutter, Gdm, Gio, GLib } = imports.gi;
-const Signals = imports.misc.signals;
-
-const Batch = imports.gdm.batch;
-const OVirt = imports.gdm.oVirt;
-const Vmware = imports.gdm.vmware;
-const Main = imports.ui.main;
-const { loadInterfaceXML } = imports.misc.fileUtils;
-const SmartcardManager = imports.misc.smartcardManager;
+import Clutter from 'gi://Clutter';
+import Gdm from 'gi://Gdm';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import * as Signals from '../misc/signals.js';
+
+import * as Batch from './batch.js';
+import * as OVirt from './oVirt.js';
+import * as Vmware from './vmware.js';
+import Main from '../ui/main.js';
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
+import * as SmartcardManager from '../misc/smartcardManager.js';
const FprintManagerIface = loadInterfaceXML('net.reactivated.Fprint.Manager');
const FprintManagerProxy = Gio.DBusProxy.makeProxyWrapper(FprintManagerIface);
@@ -27,29 +30,29 @@ Gio._promisify(Gdm.UserVerifierProxy.prototype,
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification', 'call_begin_verification_finish');
-var PASSWORD_SERVICE_NAME = 'gdm-password';
-var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
-var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
-var FADE_ANIMATION_TIME = 160;
-var CLONE_FADE_ANIMATION_TIME = 250;
+export const PASSWORD_SERVICE_NAME = 'gdm-password';
+export const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
+export const SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
+export const FADE_ANIMATION_TIME = 160;
+export const CLONE_FADE_ANIMATION_TIME = 250;
-var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
-var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
-var FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
-var SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication';
-var BANNER_MESSAGE_KEY = 'banner-message-enable';
-var BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
-var ALLOWED_FAILURES_KEY = 'allowed-failures';
+export const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
+export const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
+export const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
+export const SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication';
+export const BANNER_MESSAGE_KEY = 'banner-message-enable';
+export const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
+export const ALLOWED_FAILURES_KEY = 'allowed-failures';
-var LOGO_KEY = 'logo';
-var DISABLE_USER_LIST_KEY = 'disable-user-list';
+export const LOGO_KEY = 'logo';
+export const DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 48ms to read each character of a PAM message
-var USER_READ_TIME = 48;
+export const USER_READ_TIME = 48;
const FINGERPRINT_ERROR_TIMEOUT_WAIT = 15;
-var MessageType = {
- // Keep messages in order by priority
+/** @enum {number} */
+export const MessageType = {
NONE: 0,
HINT: 1,
INFO: 2,
@@ -62,7 +65,7 @@ const FingerprintReaderType = {
SWIPE: 2,
};
-function fadeInActor(actor) {
+export function fadeInActor(actor) {
if (actor.opacity == 255 && actor.visible)
return null;
@@ -86,7 +89,7 @@ function fadeInActor(actor) {
return hold;
}
-function fadeOutActor(actor) {
+export function fadeOutActor(actor) {
if (!actor.visible || actor.opacity == 0) {
actor.opacity = 0;
actor.hide();
@@ -108,7 +111,7 @@ function fadeOutActor(actor) {
return hold;
}
-function cloneAndFadeOutActor(actor) {
+export function cloneAndFadeOutActor(actor) {
// Immediately hide actor so its sibling can have its space
// and position, but leave a non-reactive clone on-screen,
// so from the user's point of view it smoothly fades away
@@ -136,7 +139,7 @@ function cloneAndFadeOutActor(actor) {
return hold;
}
-var ShellUserVerifier = class extends Signals.EventEmitter {
+export class ShellUserVerifier extends Signals.EventEmitter {
constructor(client, params = {}) {
super();
diff --git a/js/gdm/vmware.js b/js/gdm/vmware.js
index 118b8af39..6373d23a4 100644
--- a/js/gdm/vmware.js
+++ b/js/gdm/vmware.js
@@ -1,13 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported getVmwareCredentialsManager */
-const Gio = imports.gi.Gio;
-const Credential = imports.gdm.credentialManager;
+import Gio from 'gi://Gio';
+import * as Credential from './credentialManager.js';
const dbusPath = '/org/vmware/viewagent/Credentials';
const dbusInterface = 'org.vmware.viewagent.Credentials';
-var SERVICE_NAME = 'gdm-vmwcred';
+export const SERVICE_NAME = 'gdm-vmwcred';
const VmwareCredentialsIface = '<node> \
<interface name="' + dbusInterface + '"> \
@@ -20,6 +19,7 @@ const VmwareCredentialsIface = '<node> \
const VmwareCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(VmwareCredentialsIface);
+/** @type {VmwareCredentialsManager | null} */
let _vmwareCredentialsManager = null;
function VmwareCredentials() {
@@ -33,7 +33,7 @@ function VmwareCredentials() {
return self;
}
-var VmwareCredentialsManager = class VmwareCredentialsManager extends Credential.CredentialManager {
+export class VmwareCredentialsManager extends Credential.CredentialManager {
constructor() {
super(SERVICE_NAME);
this._credentials = VmwareCredentials();
@@ -44,7 +44,7 @@ var VmwareCredentialsManager = class VmwareCredentialsManager extends Credential
}
};
-function getVmwareCredentialsManager() {
+export function getVmwareCredentialsManager() {
if (!_vmwareCredentialsManager)
_vmwareCredentialsManager = new VmwareCredentialsManager();
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 32d41e11e..9861f183f 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -13,6 +13,7 @@
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
+ <file>misc/fileUtilsModule.js</file>
<file>misc/gnomeSession.js</file>
<file>misc/history.js</file>
<file>misc/ibusManager.js</file>
@@ -120,7 +121,7 @@
<file>ui/workspacesView.js</file>
<file>ui/xdndHandler.js</file>
- <file>ui/components/__init__.js</file>
+ <file>ui/components.js</file>
<file>ui/components/autorunManager.js</file>
<file>ui/components/automountManager.js</file>
<file>ui/components/networkAgent.js</file>
diff --git a/js/misc/config.d.ts b/js/misc/config.d.ts
new file mode 100644
index 000000000..1f1139e26
--- /dev/null
+++ b/js/misc/config.d.ts
@@ -0,0 +1,19 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+/* The name of this package (not localized) */
+export const PACKAGE_NAME: string;
+/* The version of this package */
+export const PACKAGE_VERSION: string;
+/* 1 if gnome-bluetooth is available, 0 otherwise */
+export const HAVE_BLUETOOTH: boolean;
+/* 1 if networkmanager is available, 0 otherwise */
+export const HAVE_NETWORKMANAGER: boolean;
+/* gettext package */
+export const GETTEXT_PACKAGE: string;
+/* locale dir */
+export const LOCALEDIR: string;
+/* other standard directories */
+export const LIBEXECDIR: string;
+export const PKGDATADIR: string;
+/* g-i package versions */
+export const LIBMUTTER_API_VERSION: string;
diff --git a/js/misc/config.js.in b/js/misc/config.js.in
index f9210397a..93d905249 100644
--- a/js/misc/config.js.in
+++ b/js/misc/config.js.in
@@ -18,4 +18,4 @@ var LOCALEDIR = '@datadir@/locale';
var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
/* g-i package versions */
-var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'
+var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@';
diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js
index c86468e4b..67c797499 100644
--- a/js/misc/extensionUtils.js
+++ b/js/misc/extensionUtils.js
@@ -7,18 +7,19 @@
// Common utils for the extension system and the extension
// preferences tool
-const { Gio, GLib } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
-const Gettext = imports.gettext;
+import * as Gettext from 'gettext';
const Config = imports.misc.config;
-var ExtensionType = {
+export const ExtensionType = {
SYSTEM: 1,
PER_USER: 2,
};
-var ExtensionState = {
+export const ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
@@ -41,13 +42,36 @@ const SERIALIZED_PROPERTIES = [
'canChange',
];
+let extension;
+/** @type {typeof import('../ui/main.js').default} */
+let Main;
+
+export function _setCurrentExtension(currentExtension) {
+ extension = currentExtension;
+}
+
+/** @param {typeof import('../ui/main.js').default} main */
+export function _setMain(main) {
+ Main = main;
+}
+
+/** @typedef {object} Extension */
+
/**
* getCurrentExtension:
*
- * @returns {?object} - The current extension, or null if not called from
+ * @returns {Extension} - The current extension, or null if not called from
* an extension.
*/
-function getCurrentExtension() {
+export function getCurrentExtension() {
+ if (extension) {
+ return extension;
+ }
+
+ if (!Main) {
+ throw new Error(`getCurrentExtension cannot be called before ExtensionUtils._setMain`);
+ }
+
let stack = new Error().stack.split('\n');
let extensionStackLine;
@@ -74,7 +98,6 @@ function getCurrentExtension() {
// local import, as the module is used from outside the gnome-shell process
// as well (not this function though)
- let extensionManager = imports.ui.main.extensionManager;
let path = match[1];
let file = Gio.File.new_for_path(path);
@@ -82,7 +105,7 @@ function getCurrentExtension() {
// Walk up the directory tree, looking for an extension with
// the same UUID as a directory name.
while (file != null) {
- let extension = extensionManager.lookup(file.get_basename());
+ let extension = Main.extensionManager.lookup(file.get_basename());
if (extension !== undefined)
return extension;
file = file.get_parent();
@@ -98,7 +121,7 @@ function getCurrentExtension() {
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
-function initTranslations(domain) {
+export function initTranslations(domain) {
let extension = getCurrentExtension();
if (!extension)
@@ -176,13 +199,13 @@ function callExtensionGettextFunc(func, ...args) {
/**
* getSettings:
* @param {string=} schema - the GSettings schema id
- * @returns {Gio.Settings} - a new settings object for @schema
+ * @returns {import("gi://Gio").Settings} - a new settings object for @schema
*
* Builds and returns a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is omitted, it is taken from
* metadata['settings-schema'].
*/
-function getSettings(schema) {
+export function getSettings(schema) {
let extension = getCurrentExtension();
if (!extension)
@@ -198,8 +221,8 @@ function getSettings(schema) {
let schemaSource;
if (schemaDir.query_exists(null)) {
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
- GioSSS.get_default(),
- false);
+ GioSSS.get_default(),
+ false);
} else {
schemaSource = GioSSS.get_default();
}
@@ -216,15 +239,14 @@ function getSettings(schema) {
*
* Open the preference dialog of the current extension
*/
-function openPrefs() {
+export function openPrefs() {
const extension = getCurrentExtension();
if (!extension)
throw new Error('openPrefs() can only be called from extensions');
try {
- const extensionManager = imports.ui.main.extensionManager;
- extensionManager.openExtensionPrefs(extension.uuid, '', {});
+ Main.extensionManager.openExtensionPrefs(extension.uuid, '', {});
} catch (e) {
if (e.name === 'ImportError')
throw new Error('openPrefs() cannot be called from preferences');
@@ -232,34 +254,37 @@ function openPrefs() {
}
}
-function isOutOfDate(extension) {
+export function isOutOfDate(extension) {
const [major] = Config.PACKAGE_VERSION.split('.');
return !extension.metadata['shell-version'].some(v => v.startsWith(major));
}
-function serializeExtension(extension) {
- let obj = { ...extension.metadata };
+export function serializeExtension(extension) {
+ let obj = {};
+ Object.assign(obj, extension.metadata);
SERIALIZED_PROPERTIES.forEach(prop => {
obj[prop] = extension[prop];
});
+ /** @type {{ [key: string]: GLib.Variant<'b' | 's' | 'd'>}} */
let res = {};
for (let key in obj) {
let val = obj[key];
+ /** @type {'s' | 'd' | 'b'} */
let type;
switch (typeof val) {
- case 'string':
- type = 's';
- break;
- case 'number':
- type = 'd';
- break;
- case 'boolean':
- type = 'b';
- break;
- default:
- continue;
+ case 'string':
+ type = 's';
+ break;
+ case 'number':
+ type = 'd';
+ break;
+ case 'boolean':
+ type = 'b';
+ break;
+ default:
+ continue;
}
res[key] = GLib.Variant.new(type, val);
}
@@ -267,7 +292,7 @@ function serializeExtension(extension) {
return res;
}
-function deserializeExtension(variant) {
+export function deserializeExtension(variant) {
let res = { metadata: {} };
for (let prop in variant) {
let val = variant[prop].unpack();
@@ -282,11 +307,4 @@ function deserializeExtension(variant) {
return res;
}
-function installImporter(extension) {
- let oldSearchPath = imports.searchPath.slice(); // make a copy
- imports.searchPath = [extension.dir.get_parent().get_path()];
- // importing a "subdir" creates a new importer object that doesn't affect
- // the global one
- extension.imports = imports[extension.uuid];
- imports.searchPath = oldSearchPath;
-}
+// extension.dir.get_parent().get_path()
diff --git a/js/misc/fileUtilsModule.js b/js/misc/fileUtilsModule.js
new file mode 100644
index 000000000..b452d3679
--- /dev/null
+++ b/js/misc/fileUtilsModule.js
@@ -0,0 +1,117 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+
+const Config = imports.misc.config;
+
+export function collectFromDatadirs(subdir, includeUserDir, processFile) {
+ let dataDirs = GLib.get_system_data_dirs();
+ if (includeUserDir)
+ dataDirs.unshift(GLib.get_user_data_dir());
+
+ for (let i = 0; i < dataDirs.length; i++) {
+ let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
+ let dir = Gio.File.new_for_path(path);
+
+ let fileEnum;
+ try {
+ fileEnum = dir.enumerate_children('standard::name,standard::type',
+ Gio.FileQueryInfoFlags.NONE, null);
+ } catch (e) {
+ fileEnum = null;
+ }
+ if (fileEnum != null) {
+ let info;
+ while ((info = fileEnum.next_file(null)))
+ processFile(fileEnum.get_child(info), info);
+ }
+ }
+}
+
+export function recursivelyDeleteDir(dir, deleteParent) {
+ let children = dir.enumerate_children('standard::name,standard::type',
+ Gio.FileQueryInfoFlags.NONE, null);
+
+ let info;
+ while ((info = children.next_file(null)) != null) {
+ let type = info.get_file_type();
+ let child = dir.get_child(info.get_name());
+ if (type == Gio.FileType.REGULAR)
+ child.delete(null);
+ else if (type == Gio.FileType.DIRECTORY)
+ recursivelyDeleteDir(child, true);
+ }
+
+ if (deleteParent)
+ dir.delete(null);
+}
+
+export function recursivelyMoveDir(srcDir, destDir) {
+ let children = srcDir.enumerate_children('standard::name,standard::type',
+ Gio.FileQueryInfoFlags.NONE, null);
+
+ if (!destDir.query_exists(null))
+ destDir.make_directory_with_parents(null);
+
+ let info;
+ while ((info = children.next_file(null)) != null) {
+ let type = info.get_file_type();
+ let srcChild = srcDir.get_child(info.get_name());
+ let destChild = destDir.get_child(info.get_name());
+ if (type == Gio.FileType.REGULAR)
+ srcChild.move(destChild, Gio.FileCopyFlags.NONE, null, null);
+ else if (type == Gio.FileType.DIRECTORY)
+ recursivelyMoveDir(srcChild, destChild);
+ }
+}
+
+let _ifaceResource = null;
+function ensureIfaceResource() {
+ if (_ifaceResource)
+ return;
+
+ // don't use global.datadir so the method is usable from tests/tools
+ let dir = GLib.getenv('GNOME_SHELL_DATADIR') || Config.PKGDATADIR;
+ let path = `${dir}/gnome-shell-dbus-interfaces.gresource`;
+ _ifaceResource = Gio.Resource.load(path);
+ _ifaceResource._register();
+}
+
+export function loadInterfaceXML(iface) {
+ ensureIfaceResource();
+
+ let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
+ let f = Gio.File.new_for_uri(uri);
+
+ try {
+ let [ok_, bytes] = f.load_contents(null);
+ return imports.byteArray.toString(bytes);
+ } catch (e) {
+ log(`Failed to load D-Bus interface ${iface}`);
+ }
+
+ return null;
+}
+
+export function loadSubInterfaceXML(iface, ifaceFile) {
+ let xml = loadInterfaceXML(ifaceFile);
+ if (!xml)
+ return null;
+
+ let ifaceStartTag = `<interface name="${iface}">`;
+ let ifaceStopTag = '</interface>';
+ let ifaceStartIndex = xml.indexOf(ifaceStartTag);
+ let ifaceEndIndex = xml.indexOf(ifaceStopTag, ifaceStartIndex + 1) + ifaceStopTag.length;
+
+ let xmlHeader = '<!DOCTYPE node PUBLIC\n' +
+ '\'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\'\n' +
+ '\'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\'>\n' +
+ '<node>\n';
+ let xmlFooter = '</node>';
+
+ return (
+ xmlHeader +
+ xml.substr(ifaceStartIndex, ifaceEndIndex - ifaceStartIndex) +
+ xmlFooter);
+}
diff --git a/js/misc/gnomeSession.js b/js/misc/gnomeSession.js
index a77930975..bcfc42459 100644
--- a/js/misc/gnomeSession.js
+++ b/js/misc/gnomeSession.js
@@ -1,21 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PresenceStatus, Presence, Inhibitor, SessionManager, InhibitFlags */
-const Gio = imports.gi.Gio;
+import Gio from 'gi://Gio';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from "../misc/fileUtilsModule.js";
const PresenceIface = loadInterfaceXML('org.gnome.SessionManager.Presence');
-var PresenceStatus = {
+/** @enum {number} */
+export const PresenceStatus = {
AVAILABLE: 0,
INVISIBLE: 1,
BUSY: 2,
IDLE: 3,
};
-var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
-function Presence(initCallback, cancellable) {
+export const PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
+export function Presence(initCallback, cancellable) {
return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
'/org/gnome/SessionManager/Presence', initCallback, cancellable);
}
@@ -25,18 +26,18 @@ function Presence(initCallback, cancellable) {
// of new inhibitors)
const InhibitorIface = loadInterfaceXML('org.gnome.SessionManager.Inhibitor');
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
-function Inhibitor(objectPath, initCallback, cancellable) {
+export function Inhibitor(objectPath, initCallback, cancellable) {
return InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
}
// Not the full interface, only the methods we use
const SessionManagerIface = loadInterfaceXML('org.gnome.SessionManager');
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
-function SessionManager(initCallback, cancellable) {
+export function SessionManager(initCallback, cancellable) {
return SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
}
-var InhibitFlags = {
+export const InhibitFlags = {
LOGOUT: 1 << 0,
SWITCH: 1 << 1,
SUSPEND: 1 << 2,
diff --git a/js/misc/history.js b/js/misc/history.js
index b8b66b7e0..30b694d7c 100644
--- a/js/misc/history.js
+++ b/js/misc/history.js
@@ -1,12 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported HistoryManager */
-const Signals = imports.misc.signals;
-const Clutter = imports.gi.Clutter;
+import * as Signals from './signals.js';
+import Clutter from 'gi://Clutter';
var DEFAULT_LIMIT = 512;
-var HistoryManager = class extends Signals.EventEmitter {
+/**
+ * @typedef {object} HistoryManagerParams
+ * @property {string | null} gsettingsKey
+ * @property {number} limit
+ * @property {Clutter.Text} entry
+ */
+
+ export class HistoryManager extends Signals.EventEmitter {
+ /**
+ * @param {Partial<HistoryManagerParams>} params
+ */
constructor(params = {}) {
super();
diff --git a/js/misc/ibusManager.js b/js/misc/ibusManager.js
index 056bf543f..9e9f707b6 100644
--- a/js/misc/ibusManager.js
+++ b/js/misc/ibusManager.js
@@ -1,10 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported getIBusManager */
-const { Gio, GLib, IBus, Meta } = imports.gi;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import IBus from 'gi://IBus';
+import Meta from 'gi://Meta';
+import * as Signals from './signals.js';
-const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
+import * as IBusCandidatePopup from '../ui/ibusCandidatePopup.js';
Gio._promisify(IBus.Bus.prototype,
'list_engines_async', 'list_engines_async_finish');
@@ -18,6 +20,7 @@ Gio._promisify(IBus.Bus.prototype,
// Ensure runtime version matches
_checkIBusVersion(1, 5, 2);
+/** @type {IBusManager | null} */
let _ibusManager = null;
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
@@ -32,13 +35,13 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
requiredMajor, requiredMinor, requiredMicro);
}
-function getIBusManager() {
+export function getIBusManager() {
if (_ibusManager == null)
_ibusManager = new IBusManager();
return _ibusManager;
}
-var IBusManager = class extends Signals.EventEmitter {
+export class IBusManager extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js
index 25b02e35b..67e153089 100644
--- a/js/misc/inputMethod.js
+++ b/js/misc/inputMethod.js
@@ -1,15 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */
-const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import IBus from 'gi://IBus';
-const Keyboard = imports.ui.status.keyboard;
+import * as Keyboard from '../ui/status/keyboard.js';
Gio._promisify(IBus.Bus.prototype,
'create_input_context_async', 'create_input_context_async_finish');
-var HIDE_PANEL_TIME = 50;
+export let HIDE_PANEL_TIME = 50;
-var InputMethod = GObject.registerClass(
+export const InputMethod = GObject.registerClass(
class InputMethod extends Clutter.InputMethod {
_init() {
super._init();
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 22bd8319c..2a0c7d38a 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -1,5 +1,9 @@
/* exported IntrospectService */
-const { Gio, GLib, Meta, Shell, St } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
const APP_ALLOWLIST = [
'org.freedesktop.impl.portal.desktop.gtk',
@@ -8,12 +12,12 @@ const APP_ALLOWLIST = [
const INTROSPECT_DBUS_API_VERSION = 3;
-const { loadInterfaceXML } = imports.misc.fileUtils;
-const { DBusSenderChecker } = imports.misc.util;
+import { loadInterfaceXML } from "./fileUtilsModule.js";
+import { DBusSenderChecker } from "./util.js";
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
-var IntrospectService = class {
+export class IntrospectService {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(IntrospectDBusIface,
this);
@@ -131,6 +135,7 @@ var IntrospectService = class {
GetWindowsAsync(params, invocation) {
let focusWindow = global.display.get_focus_window();
let apps = this._appSystem.get_running();
+ /** @type {{ [key: number]: { [key: string]: GLib.Variant }}} */
let windowsList = {};
try {
diff --git a/js/misc/jsParse.js b/js/misc/jsParse.js
index c4e077f62..293dd6f5a 100644
--- a/js/misc/jsParse.js
+++ b/js/misc/jsParse.js
@@ -1,5 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
// Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
@@ -7,7 +6,7 @@
// consist of global constants that might not carry over from the calling environment.
//
// This function is likely the one you want to call from external modules
-function getCompletions(text, commandHeader, globalCompletionList) {
+export function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr_, base;
let attrHead = '';
@@ -108,7 +107,7 @@ function findTheBrace(expr, offset, ...braces) {
// There is no guarantee of correct javascript syntax between the return
// value and offset. This function is meant to take a string like
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
-function getExpressionOffset(expr, offset) {
+export function getExpressionOffset(expr, offset) {
while (offset >= 0) {
let currChar = expr.charAt(offset);
@@ -132,7 +131,7 @@ function isValidPropertyName(w) {
// To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves
-function getAllProps(obj) {
+export function getAllProps(obj) {
if (obj === null || obj === undefined)
return [];
@@ -144,7 +143,7 @@ function getAllProps(obj) {
// e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _.
-function getPropertyNamesFromExpression(expr, commandHeader = '') {
+export function getPropertyNamesFromExpression(expr, commandHeader = '') {
let obj = {};
if (!isUnsafeExpression(expr)) {
try {
@@ -170,7 +169,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
}
// Given a list of words, returns the longest prefix they all have in common
-function getCommonPrefix(words) {
+export function getCommonPrefix(words) {
let word = words[0];
for (let i = 0; i < word.length; i++) {
for (let w = 1; w < words.length; w++) {
@@ -221,7 +220,7 @@ function isUnsafeExpression(str) {
}
// Returns a list of global keywords derived from str
-function getDeclaredConstants(str) {
+export function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(s => {
let base_, keyword;
diff --git a/js/misc/keyboardManager.js b/js/misc/keyboardManager.js
index 142e2f419..f51224c91 100644
--- a/js/misc/keyboardManager.js
+++ b/js/misc/keyboardManager.js
@@ -1,42 +1,43 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
-const { GLib, GnomeDesktop } = imports.gi;
+import GLib from 'gi://GLib';
+import GnomeDesktop from 'gi://GnomeDesktop';
-const Main = imports.ui.main;
+import Main from "../ui/main.js";
-var DEFAULT_LOCALE = 'en_US';
-var DEFAULT_LAYOUT = 'us';
-var DEFAULT_VARIANT = '';
+export let DEFAULT_LOCALE = 'en_US';
+export let DEFAULT_LAYOUT = 'us';
+export let DEFAULT_VARIANT = '';
let _xkbInfo = null;
-function getXkbInfo() {
+export function getXkbInfo() {
if (_xkbInfo == null)
_xkbInfo = new GnomeDesktop.XkbInfo();
return _xkbInfo;
}
+/** @type {KeyboardManager | null} */
let _keyboardManager = null;
-function getKeyboardManager() {
+export function getKeyboardManager() {
if (_keyboardManager == null)
_keyboardManager = new KeyboardManager();
return _keyboardManager;
}
-function releaseKeyboard() {
+export function releaseKeyboard() {
if (Main.modalCount > 0)
global.display.unfreeze_keyboard(global.get_current_time());
else
global.display.ungrab_keyboard(global.get_current_time());
}
-function holdKeyboard() {
+export function holdKeyboard() {
global.display.freeze_keyboard(global.get_current_time());
}
-var KeyboardManager = class {
+export class KeyboardManager {
constructor() {
// The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can
diff --git a/js/misc/loginManager.js b/js/misc/loginManager.js
index f5ebaf657..7f33763a6 100644
--- a/js/misc/loginManager.js
+++ b/js/misc/loginManager.js
@@ -1,10 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported canLock, getLoginManager, registerSessionWithGDM */
-const { GLib, Gio } = imports.gi;
-const Signals = imports.misc.signals;
+import GLib from 'gi://GLib';
+import Gio from 'gi://Gio';
+import * as Signals from './signals.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from "./fileUtilsModule.js";
const SystemdLoginManagerIface = loadInterfaceXML('org.freedesktop.login1.Manager');
const SystemdLoginSessionIface = loadInterfaceXML('org.freedesktop.login1.Session');
@@ -32,7 +32,7 @@ function versionCompare(required, reference) {
return true;
}
-function canLock() {
+export function canLock() {
try {
let params = GLib.Variant.new('(ss)', ['org.gnome.DisplayManager.Manager', 'Version']);
let result = Gio.DBus.system.call_sync('org.gnome.DisplayManager',
@@ -49,8 +49,7 @@ function canLock() {
}
}
-
-async function registerSessionWithGDM() {
+export async function registerSessionWithGDM() {
log("Registering session with GDM");
try {
await Gio.DBus.system.call(
@@ -68,6 +67,7 @@ async function registerSessionWithGDM() {
}
}
+/** @type {LoginManagerSystemd | LoginManagerDummy | null} */
let _loginManager = null;
/**
@@ -76,7 +76,7 @@ let _loginManager = null;
* @returns {object} - the LoginManager singleton
*
*/
-function getLoginManager() {
+export function getLoginManager() {
if (_loginManager == null) {
if (haveSystemd())
_loginManager = new LoginManagerSystemd();
@@ -87,7 +87,7 @@ function getLoginManager() {
return _loginManager;
}
-var LoginManagerSystemd = class extends Signals.EventEmitter {
+export class LoginManagerSystemd extends Signals.EventEmitter {
constructor() {
super();
@@ -205,7 +205,7 @@ var LoginManagerSystemd = class extends Signals.EventEmitter {
}
};
-var LoginManagerDummy = class extends Signals.EventEmitter {
+export class LoginManagerDummy extends Signals.EventEmitter {
getCurrentSessionProxy(_callback) {
// we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal()
diff --git a/js/misc/modemManager.js b/js/misc/modemManager.js
index 912acd349..9c0c3b326 100644
--- a/js/misc/modemManager.js
+++ b/js/misc/modemManager.js
@@ -1,9 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModemBase, ModemGsm, ModemCdma, BroadbandModem */
-const { Gio, GObject, NM, NMA } = imports.gi;
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import NM from 'gi://NM';
+import NMA from 'gi://NMA';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from "./fileUtilsModule.js";
// _getMobileProvidersDatabase:
//
@@ -98,7 +101,7 @@ const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInter
const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma');
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
-var ModemBase = GObject.registerClass({
+export const ModemBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'operator-name': GObject.ParamSpec.string(
@@ -111,8 +114,8 @@ var ModemBase = GObject.registerClass({
0, 100, 0),
},
}, class ModemBase extends GObject.Object {
- _init() {
- super._init();
+ _init(...args) {
+ super._init(...args);
this._operatorName = null;
this._signalQuality = 0;
}
@@ -140,7 +143,7 @@ var ModemBase = GObject.registerClass({
}
});
-var ModemGsm = GObject.registerClass(
+export const ModemGsm = GObject.registerClass(
class ModemGsm extends ModemBase {
_init(path) {
super._init();
@@ -174,7 +177,7 @@ class ModemGsm extends ModemBase {
}
});
-var ModemCdma = GObject.registerClass(
+export const ModemCdma = GObject.registerClass(
class ModemCdma extends ModemBase {
_init(path) {
super._init();
@@ -226,7 +229,7 @@ const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gp
const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma');
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
-var BroadbandModem = GObject.registerClass({
+export const BroadbandModem = GObject.registerClass({
Properties: {
'capabilities': GObject.ParamSpec.flags(
'capabilities', 'capabilities', 'capabilities',
diff --git a/js/misc/objectManager.js b/js/misc/objectManager.js
index a69f421ab..b9a4038a6 100644
--- a/js/misc/objectManager.js
+++ b/js/misc/objectManager.js
@@ -1,8 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ObjectManager */
-const { Gio, GLib } = imports.gi;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import * as Signals from './signals.js';
// Specified in the D-Bus specification here:
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
@@ -25,7 +26,7 @@ const ObjectManagerIface = `
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
-var ObjectManager = class extends Signals.EventEmitter {
+export class ObjectManager extends Signals.EventEmitter {
constructor(params = {}) {
super();
@@ -243,6 +244,9 @@ var ObjectManager = class extends Signals.EventEmitter {
}
}
+ /**
+ * @param {string[]} interfaces
+ */
_registerInterfaces(interfaces) {
for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
diff --git a/js/misc/params.d.ts b/js/misc/params.d.ts
new file mode 100644
index 000000000..a1362722f
--- /dev/null
+++ b/js/misc/params.d.ts
@@ -0,0 +1,6 @@
+export type Anyify<D extends { [key: string]: any }> = { [key in keyof D]?: any };
+
+export function parse<D extends { [key: string]: any }, P extends { [key: string]: any }>(params: P, defaults: D, allowExtras: true): D & typeof params;
+export function parse<D extends { [key: string]: any }, P extends Anyify<D>>(params: P, defaults: D, allowExtras: false): D;
+export function parse<D extends { [key: string]: any }, P extends Anyify<D>>(params: P, defaults: D): D;
+export function parse<D extends { [key: string]: any }, P extends Anyify<D> | { [key: string]: any }>(params: P, defaults: D, allowExtras: boolean): D | D & typeof params;
diff --git a/js/misc/params.js b/js/misc/params.js
index 817d66ceb..32ddbf692 100644
--- a/js/misc/params.js
+++ b/js/misc/params.js
@@ -15,7 +15,7 @@
//
// Return value: a new object, containing the merged parameters from
// @params and @defaults
-function parse(params = {}, defaults, allowExtras) {
+export function parse(params = {}, defaults, allowExtras) {
if (!allowExtras) {
for (let prop in params) {
if (!(prop in defaults))
diff --git a/js/misc/parentalControlsManager.js b/js/misc/parentalControlsManager.js
index fc1e7ced6..5b42e0715 100644
--- a/js/misc/parentalControlsManager.js
+++ b/js/misc/parentalControlsManager.js
@@ -21,23 +21,24 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-/* exported getDefault */
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
-const { Gio, GObject, Shell } = imports.gi;
+import gi from 'gi';
// We require libmalcontent ≥ 0.6.0
-const HAVE_MALCONTENT = imports.package.checkSymbol(
- 'Malcontent', '0', 'ManagerGetValueFlags');
+const HAVE_MALCONTENT = true;
-var Malcontent = null;
+let Malcontent = null;
if (HAVE_MALCONTENT) {
- Malcontent = imports.gi.Malcontent;
+ Malcontent = gi.require('Malcontent');
Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async', 'get_app_filter_finish');
}
let _singleton = null;
-function getDefault() {
+export function getDefault() {
if (_singleton === null)
_singleton = new ParentalControlsManager();
@@ -48,7 +49,7 @@ function getDefault() {
// parental controls settings. It’s possible for the user’s parental controls
// to change at runtime if the Parental Controls application is used by an
// administrator from within the user’s session.
-var ParentalControlsManager = GObject.registerClass({
+export const ParentalControlsManager = GObject.registerClass({
Signals: {
'app-filter-changed': {},
},
diff --git a/js/misc/permissionStore.js b/js/misc/permissionStore.js
index 14fc47f7e..368355406 100644
--- a/js/misc/permissionStore.js
+++ b/js/misc/permissionStore.js
@@ -1,14 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PermissionStore */
-const Gio = imports.gi.Gio;
+import Gio from 'gi://Gio';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from "./fileUtilsModule.js";
const PermissionStoreIface = loadInterfaceXML('org.freedesktop.impl.portal.PermissionStore');
const PermissionStoreProxy = Gio.DBusProxy.makeProxyWrapper(PermissionStoreIface);
-function PermissionStore(initCallback, cancellable) {
+export function PermissionStore(initCallback, cancellable) {
return PermissionStoreProxy(Gio.DBus.session,
'org.freedesktop.impl.portal.PermissionStore',
'/org/freedesktop/impl/portal/PermissionStore',
diff --git a/js/misc/signals.d.ts b/js/misc/signals.d.ts
new file mode 100644
index 000000000..616198048
--- /dev/null
+++ b/js/misc/signals.d.ts
@@ -0,0 +1,9 @@
+export type EventId = number;
+
+export class EventEmitter {
+ connect(event: string, handler: (...args: any[]) => any): EventId;
+ disconnect(id: EventId);
+ emit(event: string, ...args: any[]);
+ disconnectAll();
+ signalHandlerIsConnected(event: string);
+}
diff --git a/js/misc/signals.js b/js/misc/signals.js
index 48b3429f3..2eb6d3254 100644
--- a/js/misc/signals.js
+++ b/js/misc/signals.js
@@ -1,5 +1,6 @@
+/** @type {import("environment").SignalsNamespace} */
const Signals = imports.signals;
-var EventEmitter = class EventEmitter {};
+export class EventEmitter {}
Signals.addSignalMethods(EventEmitter.prototype);
diff --git a/js/misc/smartcardManager.js b/js/misc/smartcardManager.js
index 0e03ab86d..75ed354bd 100644
--- a/js/misc/smartcardManager.js
+++ b/js/misc/smartcardManager.js
@@ -1,10 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported getSmartcardManager */
-const Gio = imports.gi.Gio;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import * as Signals from './signals.js';
-const ObjectManager = imports.misc.objectManager;
+import * as ObjectManager from "./objectManager.js";
const SmartcardTokenIface = `
<node>
@@ -16,16 +15,17 @@ const SmartcardTokenIface = `
</interface>
</node>`;
+/** @type {SmartcardManager | null} */
let _smartcardManager = null;
-function getSmartcardManager() {
+export function getSmartcardManager() {
if (_smartcardManager == null)
_smartcardManager = new SmartcardManager();
return _smartcardManager;
}
-var SmartcardManager = class extends Signals.EventEmitter {
+export class SmartcardManager extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/misc/systemActions.js b/js/misc/systemActions.js
index 10cab9a9e..fba24c371 100644
--- a/js/misc/systemActions.js
+++ b/js/misc/systemActions.js
@@ -1,9 +1,17 @@
/* exported getDefault */
-const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
+import AccountsService from 'gi://AccountsService';
+import Clutter from 'gi://Clutter';
+import Gdm from 'gi://Gdm';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
-const GnomeSession = imports.misc.gnomeSession;
-const LoginManager = imports.misc.loginManager;
-const Main = imports.ui.main;
+
+import * as GnomeSession from "./gnomeSession.js";
+import * as LoginManager from "./loginManager.js";
+
+import Main from "../ui/main.js";
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
@@ -23,7 +31,7 @@ const LOCK_ORIENTATION_ACTION_ID = 'lock-orientation';
let _singleton = null;
-function getDefault() {
+export function getDefault() {
if (_singleton == null)
_singleton = new SystemActions();
@@ -137,7 +145,8 @@ const SystemActions = GObject.registerClass({
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
this._orientationSettings = new Gio.Settings({ schema_id: 'org.gnome.settings-daemon.peripherals.touchscreen' });
- this._session = new GnomeSession.SessionManager();
+ // FIXME
+ this._session = GnomeSession.SessionManager();
this._loginManager = LoginManager.getLoginManager();
this._monitorManager = Meta.MonitorManager.get();
diff --git a/js/misc/util.js b/js/misc/util.js
index dd25eacce..4a54606e4 100644
--- a/js/misc/util.js
+++ b/js/misc/util.js
@@ -4,12 +4,18 @@
ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare,
DBusSenderChecker */
-const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
-const Gettext = imports.gettext;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import GnomeDesktop from 'gi://GnomeDesktop';
-const Main = imports.ui.main;
+import Main from "../ui/main.js";
-var SCROLL_TIME = 100;
+import * as Gettext from 'gettext';
+
+export let SCROLL_TIME = 100;
const WIGGLE_OFFSET = 6;
const WIGGLE_DURATION = 65;
@@ -52,7 +58,7 @@ let _desktopSettings = null;
// the position within @str where the URL was found.
//
// Return value: the list of match objects, as described above
-function findUrls(str) {
+export function findUrls(str) {
let res = [], match;
while ((match = _urlRegexp.exec(str)))
res.push({ url: match[2], pos: match.index + match[1].length });
@@ -64,7 +70,7 @@ function findUrls(str) {
//
// Runs @argv in the background, handling any errors that occur
// when trying to start the program.
-function spawn(argv) {
+export function spawn(argv) {
try {
trySpawn(argv);
} catch (err) {
@@ -77,7 +83,7 @@ function spawn(argv) {
//
// Runs @commandLine in the background, handling any errors that
// occur when trying to parse or start the program.
-function spawnCommandLine(commandLine) {
+export function spawnCommandLine(commandLine) {
try {
let [success_, argv] = GLib.shell_parse_argv(commandLine);
trySpawn(argv);
@@ -90,7 +96,7 @@ function spawnCommandLine(commandLine) {
// @argv: an argv array
//
// Runs @argv as if it was an application, handling startup notification
-function spawnApp(argv) {
+export function spawnApp(argv) {
try {
let app = Gio.AppInfo.create_from_commandline(argv.join(' '), null,
Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION);
@@ -108,7 +114,7 @@ function spawnApp(argv) {
// Runs @argv in the background. If launching @argv fails,
// this will throw an error.
function trySpawn(argv) {
- var success_, pid;
+ let success_, pid;
try {
[success_, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
@@ -145,7 +151,7 @@ function trySpawn(argv) {
//
// Runs @commandLine in the background. If launching @commandLine
// fails, this will throw an error.
-function trySpawnCommandLine(commandLine) {
+export function trySpawnCommandLine(commandLine) {
let success_, argv;
try {
@@ -165,7 +171,7 @@ function _handleSpawnError(command, err) {
Main.notifyError(title, err.message);
}
-function formatTimeSpan(date) {
+export function formatTimeSpan(date) {
let now = GLib.DateTime.new_now_local();
let timespan = now.difference(date);
@@ -205,7 +211,17 @@ function formatTimeSpan(date) {
"%d years ago", yearsAgo).format(yearsAgo);
}
-function formatTime(time, params = {}) {
+/**
+ * @typedef {object} FormatTimeProps
+ * @property {boolean} timeOnly
+ * @property {boolean} ampm
+ */
+
+/**
+ * @param {GLib.DateTime | Date} time
+ * @param {Partial<FormatTimeProps>} params
+ */
+export function formatTime(time, params) {
let date;
// HACK: The built-in Date type sucks at timezones, which we need for the
// world clock; it's often more convenient though, so allow either
@@ -300,7 +316,7 @@ function formatTime(time, params = {}) {
return formattedTime.replace(/([:\u2236])/g, '\u200e$1');
}
-function createTimeLabel(date, params) {
+export function createTimeLabel(date, params) {
if (_desktopSettings == null)
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
@@ -356,14 +372,14 @@ function lowerBound(array, val, cmp) {
// Inserts @val into @array, preserving the
// sorting invariants.
// Returns the position at which it was inserted
-function insertSorted(array, val, cmp) {
+export function insertSorted(array, val, cmp) {
let pos = lowerBound(array, val, cmp);
array.splice(pos, 0, val);
return pos;
}
-function ensureActorVisibleInScrollView(scrollView, actor) {
+export function ensureActorVisibleInScrollView(scrollView, actor) {
let adjustment = scrollView.vscroll.adjustment;
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
@@ -399,7 +415,18 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
});
}
-function wiggle(actor, params = {}) {
+/**
+ * @typedef {object} WiggleProps
+ * @property {number} offset
+ * @property {number} duration
+ * @property {number} wiggleCount
+ */
+
+/**
+ * @param {Clutter.Actor} actor
+ * @param {Partial<WiggleProps>} [params]
+ */
+export function wiggle(actor, params = {}) {
if (!St.Settings.get().enable_animations)
return;
@@ -436,7 +463,7 @@ function wiggle(actor, params = {}) {
});
}
-function lerp(start, end, progress) {
+export function lerp(start, end, progress) {
return start + progress * (end - start);
}
@@ -462,7 +489,7 @@ function _GNOMEversionToNumber(version) {
//
// Returns an integer less than, equal to, or greater than
// zero, if version1 is older, equal or newer than version2
-function GNOMEversionCompare(version1, version2) {
+export function GNOMEversionCompare(version1, version2) {
const v1Array = version1.split('.');
const v2Array = version2.split('.');
@@ -478,7 +505,7 @@ function GNOMEversionCompare(version1, version2) {
return 0;
}
-var DBusSenderChecker = class {
+export class DBusSenderChecker {
/**
* @param {string[]} allowList - list of allowed well-known names
*/
diff --git a/js/misc/weather.js b/js/misc/weather.js
index 5d6cca1ea..eca6c3d78 100644
--- a/js/misc/weather.js
+++ b/js/misc/weather.js
@@ -1,12 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WeatherClient */
-const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
-const Signals = imports.misc.signals;
+import Geoclue from 'gi://Geoclue';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GWeather from 'gi://GWeather';
+import Shell from 'gi://Shell';
+import * as Signals from './signals.js';
-const PermissionStore = imports.misc.permissionStore;
+import * as PermissionStore from "./permissionStore.js";
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from "./fileUtilsModule.js";
Gio._promisify(Geoclue.Simple, 'new', 'new_finish');
@@ -18,10 +22,11 @@ const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
+export let UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
+
// Minimum time between updates to show loading indication
-var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
-var WeatherClient = class extends Signals.EventEmitter {
+export class WeatherClient extends Signals.EventEmitter {
constructor() {
super();
@@ -293,7 +298,7 @@ var WeatherClient = class extends Signals.EventEmitter {
}
_onLocationsChanged() {
- let locations = this._settings.get_value('locations').deep_unpack();
+ let locations = /** @type {GLib.Variant<'av'>} */ (this._settings.get_value('locations')).deep_unpack();
let serialized = locations.shift();
let mostRecentLocation = null;
diff --git a/js/perf/basic.js b/js/perf/basic.js
index 718532f28..9f05c6d76 100644
--- a/js/perf/basic.js
+++ b/js/perf/basic.js
@@ -5,15 +5,16 @@
*/
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_"] }] */
-const { St } = imports.gi;
+import St from 'gi://St';
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const Scripting = imports.ui.scripting;
+import Main from "../ui/main.js";
+
+import * as MessageTray from "../ui/messageTray.js";
+import * as Scripting from "../ui/scripting.js";
// This script tests the most important (basic) functionality of the shell.
-var METRICS = {};
+export const METRICS = {};
async function run() {
/* eslint-disable no-await-in-loop */
diff --git a/js/perf/core.js b/js/perf/core.js
index f3f496b03..da5ba378f 100644
--- a/js/perf/core.js
+++ b/js/perf/core.js
@@ -5,17 +5,17 @@
clutter_stagePaintDone */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^malloc", "^glx", "^clutter"] }] */
-const System = imports.system;
+import System from 'system';
-const Main = imports.ui.main;
-const Scripting = imports.ui.scripting;
+import Main from "../ui/main.js";
+import * as Scripting from "../ui/scripting.js";
// This performance script measure the most important (core) performance
// metrics for the shell. By looking at the output metrics of this script
// someone should be able to get an idea of how well the shell is performing
// on a particular system.
-var METRICS = {
+export const METRICS = {
overviewLatencyFirst:
{ description: "Time to first frame after triggering overview, first time",
units: "us" },
diff --git a/js/perf/hwtest.js b/js/perf/hwtest.js
index 0f396acd3..321e61960 100644
--- a/js/perf/hwtest.js
+++ b/js/perf/hwtest.js
@@ -7,11 +7,14 @@
script_geditLaunch, script_geditFirstFrame,
clutter_stagePaintStart, clutter_paintCompletedTimestamp */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^clutter"] }] */
-const { Clutter, Gio, Shell } = imports.gi;
-const Main = imports.ui.main;
-const Scripting = imports.ui.scripting;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import Shell from 'gi://Shell';
-var METRICS = {
+import Main from "../ui/main.js";
+import * as Scripting from "../ui/scripting.js";
+
+export const METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
diff --git a/js/ui/accessDialog.js b/js/ui/accessDialog.js
index 7c8d69b80..dac1ed50d 100644
--- a/js/ui/accessDialog.js
+++ b/js/ui/accessDialog.js
@@ -1,22 +1,29 @@
/* exported AccessDialogDBus */
-const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const CheckBox = imports.ui.checkBox;
-const Dialog = imports.ui.dialog;
-const ModalDialog = imports.ui.modalDialog;
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import * as CheckBox from './checkBox.js';
+import * as Dialog from './dialog.js';
+import * as ModalDialog from './modalDialog.js';
+
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const RequestIface = loadInterfaceXML('org.freedesktop.impl.portal.Request');
const AccessIface = loadInterfaceXML('org.freedesktop.impl.portal.Access');
-var DialogResponse = {
+/** @enum {number} */
+export const DialogResponse = {
OK: 0,
CANCEL: 1,
CLOSED: 2,
};
-var AccessDialog = GObject.registerClass(
+export const AccessDialog = GObject.registerClass(
class AccessDialog extends ModalDialog.ModalDialog {
_init(invocation, handle, title, description, body, options) {
super._init({ styleClass: 'access-dialog' });
@@ -100,6 +107,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this._request.unexport();
this._requestExported = false;
+ /** @type {{ [key: string]: GLib.Variant<'s'> }} */
let results = {};
if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) {
@@ -117,7 +125,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
}
});
-var AccessDialogDBus = class {
+export class AccessDialogDBus {
constructor() {
this._accessDialog = null;
diff --git a/js/ui/altTab.js b/js/ui/altTab.js
index 6af9380ed..f428f3fbb 100644
--- a/js/ui/altTab.js
+++ b/js/ui/altTab.js
@@ -2,24 +2,33 @@
/* exported AppSwitcherPopup, GroupCyclerPopup, WindowSwitcherPopup,
WindowCyclerPopup */
-const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Main = imports.ui.main;
-const SwitcherPopup = imports.ui.switcherPopup;
-var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
+import Main from './main.js';
+import * as SwitcherPopup from './switcherPopup.js';
-var THUMBNAIL_DEFAULT_SIZE = 256;
-var THUMBNAIL_POPUP_TIME = 500; // milliseconds
-var THUMBNAIL_FADE_TIME = 100; // milliseconds
+export let APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
-var WINDOW_PREVIEW_SIZE = 128;
-var APP_ICON_SIZE = 96;
-var APP_ICON_SIZE_SMALL = 48;
+export let THUMBNAIL_DEFAULT_SIZE = 256;
+export let THUMBNAIL_POPUP_TIME = 500; // milliseconds
+export let THUMBNAIL_FADE_TIME = 100; // milliseconds
+
+export let WINDOW_PREVIEW_SIZE = 128;
+export let APP_ICON_SIZE = 96;
+export let APP_ICON_SIZE_SMALL = 48;
const baseIconSizes = [96, 64, 48, 32, 22];
-var AppIconMode = {
+/** @enum {number} */
+export const AppIconMode = {
THUMBNAIL_ONLY: 1,
APP_ICON_ONLY: 2,
BOTH: 3,
@@ -38,7 +47,7 @@ function _createWindowClone(window, size) {
y_expand: true });
}
-function getWindows(workspace) {
+export function getWindows(workspace) {
// We ignore skip-taskbar windows in switchers, but if they are attached
// to their parent, their position in the MRU list may be more appropriate
// than the parent; so start with the complete list ...
@@ -51,7 +60,7 @@ function getWindows(workspace) {
}).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
}
-var AppSwitcherPopup = GObject.registerClass(
+export const AppSwitcherPopup = GObject.registerClass(
class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_init() {
super._init();
@@ -290,8 +299,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
/**
* _select:
* @param {number} app: index of the app to select
- * @param {number=} window: index of which of @app's windows to select
- * @param {bool} forceAppFocus: optional flag, see below
+ * @param {number} [window]: index of which of @app's windows to select
+ * @param {boolean} [forceAppFocus]: optional flag, see below
*
* Selects the indicated @app, and optional @window, and sets
* this._thumbnailsFocused appropriately to indicate whether the
@@ -397,13 +406,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
});
-var CyclerHighlight = GObject.registerClass(
+export const CyclerHighlight = GObject.registerClass(
class CyclerHighlight extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null;
this._sizeChangedId = 0;
+ /** @type {Clutter.Clone<Meta.WindowActor>} */
this._clone = new Clutter.Clone();
this.add_actor(this._clone);
@@ -465,7 +475,7 @@ class CyclerHighlight extends St.Widget {
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
-var CyclerList = GObject.registerClass({
+export const CyclerList = GObject.registerClass({
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
'item-entered': { param_types: [GObject.TYPE_INT] },
'item-removed': { param_types: [GObject.TYPE_INT] },
@@ -476,7 +486,7 @@ var CyclerList = GObject.registerClass({
}
});
-var CyclerPopup = GObject.registerClass({
+export const CyclerPopup = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
}, class CyclerPopup extends SwitcherPopup.SwitcherPopup {
_init() {
@@ -493,6 +503,13 @@ var CyclerPopup = GObject.registerClass({
});
}
+ /**
+ * @returns {Meta.Window[]}
+ */
+ _getWindows() {
+ throw new GObject.NotImplementedError(`_getWindows in ${this.constructor.name}`);
+ }
+
_highlightItem(index, _justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight, null);
@@ -532,7 +549,7 @@ var CyclerPopup = GObject.registerClass({
});
-var GroupCyclerPopup = GObject.registerClass(
+export const GroupCyclerPopup = GObject.registerClass(
class GroupCyclerPopup extends CyclerPopup {
_init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' });
@@ -565,7 +582,7 @@ class GroupCyclerPopup extends CyclerPopup {
}
});
-var WindowSwitcherPopup = GObject.registerClass(
+export const WindowSwitcherPopup = GObject.registerClass(
class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_init() {
super._init();
@@ -623,7 +640,7 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
});
-var WindowCyclerPopup = GObject.registerClass(
+export const WindowCyclerPopup = GObject.registerClass(
class WindowCyclerPopup extends CyclerPopup {
_init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
@@ -654,12 +671,15 @@ class WindowCyclerPopup extends CyclerPopup {
}
});
-var AppIcon = GObject.registerClass(
+export const AppIcon = GObject.registerClass(
class AppIcon extends St.BoxLayout {
_init(app) {
super._init({ style_class: 'alt-tab-app',
vertical: true });
+ /** @type {Meta.Window[]} */
+ this.cachedWindows = [];
+
this.app = app;
this.icon = null;
this._iconBin = new St.Bin();
@@ -679,7 +699,7 @@ class AppIcon extends St.BoxLayout {
}
});
-var AppSwitcher = GObject.registerClass(
+export const AppSwitcher = GObject.registerClass(
class AppSwitcher extends SwitcherPopup.SwitcherList {
_init(apps, altTabPopup) {
super._init(true);
@@ -814,6 +834,8 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
} else {
this._itemEntered(index);
}
+
+ return false;
}
_enterItem(index) {
@@ -884,7 +906,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
}
});
-var ThumbnailSwitcher = GObject.registerClass(
+export const ThumbnailSwitcher = GObject.registerClass(
class ThumbnailSwitcher extends SwitcherPopup.SwitcherList {
_init(windows) {
super._init(false);
@@ -892,6 +914,7 @@ class ThumbnailSwitcher extends SwitcherPopup.SwitcherList {
this._labels = [];
this._thumbnailBins = [];
this._clones = [];
+ /** @type {Meta.Window[]} */
this._windows = windows;
for (let i = 0; i < windows.length; i++) {
@@ -979,7 +1002,7 @@ class ThumbnailSwitcher extends SwitcherPopup.SwitcherList {
}
});
-var WindowIcon = GObject.registerClass(
+export const WindowIcon = GObject.registerClass(
class WindowIcon extends St.BoxLayout {
_init(window, mode) {
super._init({ style_class: 'alt-tab-app',
@@ -987,6 +1010,8 @@ class WindowIcon extends St.BoxLayout {
this.window = window;
+ this._unmanagedSignalId = -1;
+
this._icon = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.add_child(this._icon);
@@ -1037,7 +1062,7 @@ class WindowIcon extends St.BoxLayout {
}
});
-var WindowSwitcher = GObject.registerClass(
+export const WindowSwitcher = GObject.registerClass(
class WindowSwitcher extends SwitcherPopup.SwitcherList {
_init(windows, mode) {
super._init(true);
@@ -1070,6 +1095,9 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
});
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(forWidth) {
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
diff --git a/js/ui/animation.js b/js/ui/animation.js
index b81eb2b90..f98a13f97 100644
--- a/js/ui/animation.js
+++ b/js/ui/animation.js
@@ -1,14 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
-const { Clutter, GLib, GObject, Gio, St } = imports.gi;
-
-
-var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
-var SPINNER_ANIMATION_TIME = 300;
-var SPINNER_ANIMATION_DELAY = 1000;
-
-var Animation = GObject.registerClass(
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+import St from 'gi://St';
+
+
+export let ANIMATED_ICON_UPDATE_TIMEOUT = 16;
+export let SPINNER_ANIMATION_TIME = 300;
+export let SPINNER_ANIMATION_DELAY = 1000;
+
+/**
+ * @typedef {object} AnimationParams
+ * @property {Gio.File} file
+ * @property {number} width
+ * @property {number} height
+ * @property {number} speed
+ */
+
+export const Animation = GObject.registerClass(
class Animation extends St.Bin {
_init(file, width, height, speed) {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
@@ -129,15 +141,26 @@ class Animation extends St.Bin {
}
});
-var AnimatedIcon = GObject.registerClass(
+export const AnimatedIcon = GObject.registerClass(
class AnimatedIcon extends Animation {
_init(file, size) {
super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});
-var Spinner = GObject.registerClass(
+export const Spinner = GObject.registerClass(
class Spinner extends AnimatedIcon {
+ /**
+ * @typedef {object} SpinnerParams
+ * @property {boolean} [animate]
+ * @property {boolean} [hideOnStop]
+ */
+
+ /**
+ * _init:
+ * @param {number} size
+ * @param {SpinnerParams} [params]
+ */
_init(size, params = {}) {
const {
animate = false,
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 984844f11..0c2c3c9d8 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -1,39 +1,45 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AppDisplay, AppSearchProvider */
-const { Clutter, Gio, GLib, GObject, Graphene, Meta,
- Pango, Shell, St } = imports.gi;
-
-const AppFavorites = imports.ui.appFavorites;
-const { AppMenu } = imports.ui.appMenu;
-const BoxPointer = imports.ui.boxpointer;
-const DND = imports.ui.dnd;
-const GrabHelper = imports.ui.grabHelper;
-const IconGrid = imports.ui.iconGrid;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
-const PageIndicators = imports.ui.pageIndicators;
-const ParentalControlsManager = imports.misc.parentalControlsManager;
-const PopupMenu = imports.ui.popupMenu;
-const Search = imports.ui.search;
-const SwipeTracker = imports.ui.swipeTracker;
-const SystemActions = imports.misc.systemActions;
-
-var MENU_POPUP_TIMEOUT = 600;
-var POPDOWN_DIALOG_TIMEOUT = 500;
-
-var FOLDER_SUBICON_FRACTION = .4;
-
-var VIEWS_SWITCH_TIME = 400;
-var VIEWS_SWITCH_ANIMATION_DELAY = 100;
-
-var SCROLL_TIMEOUT_TIME = 150;
-
-var APP_ICON_SCALE_IN_TIME = 500;
-var APP_ICON_SCALE_IN_DELAY = 700;
-
-var APP_ICON_TITLE_EXPAND_TIME = 200;
-var APP_ICON_TITLE_COLLAPSE_TIME = 100;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+import Graphene from 'gi://Graphene';
+import Pango from 'gi://Pango';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AppFavorites from './appFavorites.js';
+import * as DND from './dnd.js';
+import * as GrabHelper from './grabHelper.js';
+import * as IconGrid from './iconGrid.js';
+import * as Layout from './layout.js';
+import Main from './main.js';
+import * as PageIndicators from './pageIndicators.js';
+import * as ParentalControlsManager from '../misc/parentalControlsManager.js';
+import * as PopupMenu from './popupMenu.js';
+import * as Search from './search.js';
+import * as SwipeTracker from './swipeTracker.js';
+import * as SystemActions from '../misc/systemActions.js';
+
+export const MENU_POPUP_TIMEOUT = 600;
+export const POPDOWN_DIALOG_TIMEOUT = 500;
+
+export const FOLDER_SUBICON_FRACTION = .4;
+
+export const VIEWS_SWITCH_TIME = 400;
+export const VIEWS_SWITCH_ANIMATION_DELAY = 100;
+
+export const SCROLL_TIMEOUT_TIME = 150;
+
+export const APP_ICON_SCALE_IN_TIME = 500;
+export const APP_ICON_SCALE_IN_DELAY = 700;
+
+export const APP_ICON_TITLE_EXPAND_TIME = 200;
+export const APP_ICON_TITLE_COLLAPSE_TIME = 100;
const FOLDER_DIALOG_ANIMATION_TIME = 200;
@@ -86,14 +92,9 @@ function _getFolderName(folder) {
return name;
}
-function _getViewFromIcon(icon) {
- for (let parent = icon.get_parent(); parent; parent = parent.get_parent()) {
- if (parent instanceof BaseAppView)
- return parent;
- }
- return null;
-}
-
+/**
+ * @param {readonly Shell.App[]} apps
+ */
function _findBestFolderName(apps) {
let appInfos = apps.map(app => app.get_app_info());
@@ -126,7 +127,7 @@ function _findBestFolderName(apps) {
return null;
}
-var BaseAppView = GObject.registerClass({
+export const BaseAppView = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'gesture-modes': GObject.ParamSpec.flags(
@@ -283,8 +284,9 @@ var BaseAppView = GObject.registerClass({
this._box.add_child(this._pageIndicators);
// Swipe
+ // FIXME
this._swipeTracker = new SwipeTracker.SwipeTracker(this._scrollView,
- Clutter.Orientation.HORIZONTAL, this.gestureModes);
+ Clutter.Orientation.HORIZONTAL);
this._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
this._swipeTracker.connect('begin', this._swipeBegin.bind(this));
this._swipeTracker.connect('update', this._swipeUpdate.bind(this));
@@ -395,7 +397,7 @@ var BaseAppView = GObject.registerClass({
if (hOffset === 0 && vOffset === 0)
return;
}
-
+ // @ts-expect-error
this._scrollView.update_fade_effect(
new Clutter.Margin({
left: hOffset,
@@ -725,7 +727,7 @@ var BaseAppView = GObject.registerClass({
this._swipeTracker.enabled = true;
}
- _onDragCancelled() {
+ _onDragCancelled(overview, source) {
// At this point, the positions aren't stored yet, thus _redisplay()
// will move all items to their original positions
this._redisplay();
@@ -832,6 +834,13 @@ var BaseAppView = GObject.registerClass({
return [page, position];
}
+ /**
+ * @returns {AppViewItem["prototype"][]}
+ */
+ _loadApps() {
+ throw new GObject.NotImplementedError(`_loadApps in ${this.constructor.name}`);
+ }
+
_redisplay() {
let oldApps = this._orderedItems.slice();
let oldAppIds = oldApps.map(icon => icon.id);
@@ -1348,7 +1357,7 @@ var BaseAppView = GObject.registerClass({
}
});
-var PageManager = GObject.registerClass({
+export const PageManager = GObject.registerClass({
Signals: { 'layout-changed': {} },
}, class PageManager extends GObject.Object {
_init() {
@@ -1362,8 +1371,10 @@ var PageManager = GObject.registerClass({
}
_loadPages() {
+ /** @type {GLib.Variant<'aa{sv}'>} */
const layout = global.settings.get_value('app-picker-layout');
- this._pages = layout.recursiveUnpack();
+ /** @type { { [key: string]: { [key: string]: number } }[] } */
+ this._pages = (layout.recursiveUnpack());
if (!this._updatingPages)
this.emit('layout-changed');
}
@@ -1385,11 +1396,16 @@ var PageManager = GObject.registerClass({
return [page, position];
}
- set pages(p) {
+ /**
+ * @param {{ [key: string]: { [key: string]: GLib.Variant<'i'> } }[]} p
+ */
+ updatePages(p) {
+ /** @type {{ [key: string]: GLib.Variant<'a{sv}'> }[]} */
const packedPages = [];
// Pack the icon properties as a GVariant
for (const page of p) {
+ /** @type {{ [key: string]: GLib.Variant<'a{sv}'> }} */
const pageData = {};
for (const [appId, properties] of Object.entries(page))
pageData[appId] = new GLib.Variant('a{sv}', properties);
@@ -1409,7 +1425,7 @@ var PageManager = GObject.registerClass({
}
});
-var AppDisplay = GObject.registerClass(
+export const AppDisplay = GObject.registerClass(
class AppDisplay extends BaseAppView {
_init() {
super._init({
@@ -1493,11 +1509,13 @@ class AppDisplay extends BaseAppView {
}
_savePages() {
+ /** @type {{ [key: string]: { [key: string]: GLib.Variant<'i'> } }[]} */
const pages = [];
for (let i = 0; i < this._grid.nPages; i++) {
const pageItems =
this._grid.getItemsAtPage(i).filter(c => c.visible);
+ /** @type {{ [key: string]: { [key: string]: GLib.Variant<'i'> } }} */
const pageData = {};
pageItems.forEach((item, index) => {
@@ -1508,7 +1526,7 @@ class AppDisplay extends BaseAppView {
pages.push(pageData);
}
- this._pageManager.pages = pages;
+ this._pageManager.updatePages(pages);
}
_ensurePlaceholder(source) {
@@ -1752,8 +1770,8 @@ class AppDisplay extends BaseAppView {
super._maybeMoveItem(clonedEvent);
}
- _onDragBegin(overview, source) {
- super._onDragBegin(overview, source);
+ _onDragBegin(_overview, source) {
+ super._onDragBegin();
// When dragging from a folder dialog, the dragged app icon doesn't
// exist in AppDisplay. We work around that by adding a placeholder
@@ -1778,7 +1796,7 @@ class AppDisplay extends BaseAppView {
}
_onDragCancelled(overview, source) {
- const view = _getViewFromIcon(source);
+ const view = source._getView();
if (view instanceof FolderView)
return;
@@ -1792,7 +1810,7 @@ class AppDisplay extends BaseAppView {
this._savePages();
- let view = _getViewFromIcon(source);
+ let view = source._getView();
if (view instanceof FolderView)
view.removeApp(source.app);
@@ -1860,7 +1878,7 @@ class AppDisplay extends BaseAppView {
}
});
-var AppSearchProvider = class AppSearchProvider {
+export class AppSearchProvider {
constructor() {
this._appSys = Shell.AppSystem.get_default();
this.id = 'applications';
@@ -1953,17 +1971,38 @@ var AppSearchProvider = class AppSearchProvider {
}
};
-var AppViewItem = GObject.registerClass(
+/**
+ * @typedef {object} ViewParams
+ * @property {boolean} [isDraggable]
+ * @property {boolean} [expandTitleOnHover]
+ */
+
+export const AppViewItem = GObject.registerClass(
class AppViewItem extends St.Button {
- _init(params = {}, isDraggable = true, expandTitleOnHover = true) {
+ /**
+ * @param {Partial<St.Button.ConstructorProperties> & ViewParams} [params]
+ * @param {...any} _args
+ */
+ _init(params = {}, ..._args) {
+ const {
+ isDraggable = true,
+ expandTitleOnHover = true,
+ ...buttonParams
+ } = params;
+
super._init({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
reactive: true,
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
can_focus: true,
- ...params,
+ ...buttonParams,
});
+ this._name = '';
+ this._id = '';
+ /** @type {IconGrid.BaseIcon["prototype"] | null} */
+ this.icon = null;
+
this._delegate = this;
if (isDraggable) {
@@ -2162,7 +2201,7 @@ class AppViewItem extends St.Button {
}
});
-var FolderGrid = GObject.registerClass(
+export const FolderGrid = GObject.registerClass(
class FolderGrid extends IconGrid.IconGrid {
_init() {
super._init({
@@ -2179,7 +2218,14 @@ class FolderGrid extends IconGrid.IconGrid {
}
});
-var FolderView = GObject.registerClass(
+/**
+ * @typedef {object} FolderViewParams
+ * @property {import('gi://Gio').Settings} folder
+ * @property {string} id
+ * @property {*} parentView
+ */
+
+export const FolderView = GObject.registerClass(
class FolderView extends BaseAppView {
_init(folder, id, parentView) {
super._init({
@@ -2411,7 +2457,7 @@ class FolderView extends BaseAppView {
}
});
-var FolderIcon = GObject.registerClass({
+export const FolderIcon = GObject.registerClass({
Signals: {
'apps-changed': {},
},
@@ -2519,7 +2565,7 @@ var FolderIcon = GObject.registerClass({
if (!(source instanceof AppIcon))
return false;
- let view = _getViewFromIcon(source);
+ let view = source._getView();
if (!view || !(view instanceof AppDisplay))
return false;
@@ -2590,7 +2636,7 @@ var FolderIcon = GObject.registerClass({
}
});
-var AppFolderDialog = GObject.registerClass({
+export const AppFolderDialog = GObject.registerClass({
Signals: {
'open-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
},
@@ -3079,15 +3125,22 @@ var AppFolderDialog = GObject.registerClass({
}
});
-var AppIcon = GObject.registerClass({
+/**
+ * @typedef {ViewParams} AppIconParams */
+
+export const AppIcon = GObject.registerClass({
Signals: {
'menu-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
'sync-tooltip': {},
},
}, class AppIcon extends AppViewItem {
- _init(app, iconParams = {}) {
+ /**
+ * @param {Shell.App} app
+ * @param {AppIconParams} params
+ */
+ _init(app, params = {}) {
// Get the isDraggable property without passing it on to the BaseIcon:
- const { isDraggable = true, expandTitleOnHover } = iconParams;
+ const { isDraggable = true, expandTitleOnHover } = params;
super._init({ style_class: 'app-well-app' }, isDraggable, expandTitleOnHover);
@@ -3102,8 +3155,11 @@ var AppIcon = GObject.registerClass({
this._folderPreviewId = 0;
- iconParams['createIcon'] = this._createIcon.bind(this);
- iconParams['setSizeManually'] = true;
+ const iconParams = {
+ ...params,
+ createIcon: this._createIcon.bind(this),
+ setSizeManually: true,
+ };
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this._iconContainer.add_child(this.icon);
@@ -3292,6 +3348,15 @@ var AppIcon = GObject.registerClass({
this.icon.animateZoomOutAtPos(x, y);
}
+ /**
+ * @typedef {object} WorkspaceLaunchParams
+ * @property {number} workspace
+ * @property {number} timestamp
+ */
+
+ /**
+ * @param {Partial<WorkspaceLaunchParams>} params
+ */
shellWorkspaceLaunch(params = {}) {
let { stack } = new Error();
log('shellWorkspaceLaunch is deprecated, use app.open_new_window() instead\n%s'.format(stack));
@@ -3332,7 +3397,7 @@ var AppIcon = GObject.registerClass({
}
_canAccept(source) {
- let view = _getViewFromIcon(source);
+ let view = source._getView();
return source != this &&
(source instanceof this.constructor) &&
@@ -3366,12 +3431,20 @@ var AppIcon = GObject.registerClass({
}
}
+ _getView() {
+ for (let parent = this.get_parent(); parent; parent = parent.get_parent()) {
+ if (parent instanceof BaseAppView)
+ return parent;
+ }
+ return null;
+ }
+
acceptDrop(source, actor, x) {
const accepted = super.acceptDrop(source, actor, x);
if (!accepted)
return false;
- let view = _getViewFromIcon(this);
+ let view = this._getView();
let apps = [this.id, source.id];
return view?.createFolder(apps);
diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js
index 67e74e799..d9f45afbc 100644
--- a/js/ui/appFavorites.js
+++ b/js/ui/appFavorites.js
@@ -1,11 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getAppFavorites */
-const Shell = imports.gi.Shell;
-const ParentalControlsManager = imports.misc.parentalControlsManager;
-const Signals = imports.misc.signals;
+import Shell from 'gi://Shell';
+import * as ParentalControlsManager from '../misc/parentalControlsManager.js';
+import * as Signals from '../misc/signals.js';
-const Main = imports.ui.main;
+import Main from './main.js';
// In alphabetical order
const RENAMED_DESKTOP_IDS = {
@@ -204,8 +204,8 @@ class AppFavorites extends Signals.EventEmitter {
}
}
-var appFavoritesInstance = null;
-function getAppFavorites() {
+let appFavoritesInstance = null;
+export function getAppFavorites() {
if (appFavoritesInstance == null)
appFavoritesInstance = new AppFavorites();
return appFavoritesInstance;
diff --git a/js/ui/appMenu.js b/js/ui/appMenu.js
index 87d2218cd..0ec94adc2 100644
--- a/js/ui/appMenu.js
+++ b/js/ui/appMenu.js
@@ -2,12 +2,12 @@
/* exported AppMenu */
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
-const AppFavorites = imports.ui.appFavorites;
-const Main = imports.ui.main;
-const ParentalControlsManager = imports.misc.parentalControlsManager;
-const PopupMenu = imports.ui.popupMenu;
+import * as AppFavorites from './appFavorites.js';
+import Main from './main.js';
+import * as ParentalControlsManager from '../misc/parentalControlsManager.js';
+import * as PopupMenu from './popupMenu.js';
-var AppMenu = class AppMenu extends PopupMenu.PopupMenu {
+export class AppMenu extends PopupMenu.PopupMenu {
/**
* @param {Clutter.Actor} sourceActor - actor the menu is attached to
* @param {St.Side} side - arrow side
diff --git a/js/ui/audioDeviceSelection.js b/js/ui/audioDeviceSelection.js
index 8660663f9..1371db1ca 100644
--- a/js/ui/audioDeviceSelection.js
+++ b/js/ui/audioDeviceSelection.js
@@ -1,13 +1,20 @@
/* exported AudioDeviceSelectionDBus */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import * as Dialog from './dialog.js';
+import Main from './main.js';
+import * as ModalDialog from './modalDialog.js';
-var AudioDevice = {
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
+
+export const AudioDevice = {
HEADPHONES: 1 << 0,
HEADSET: 1 << 1,
MICROPHONE: 1 << 2,
@@ -15,14 +22,20 @@ var AudioDevice = {
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
-var AudioDeviceSelectionDialog = GObject.registerClass({
+export const AudioDeviceSelectionDialog = GObject.registerClass({
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } },
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
+ /**
+ * @param {*} devices
+ */
_init(devices) {
super._init({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {};
+ /** @type {string} */
+ this._sender = null;
+
this._buildLayout();
if (devices & AudioDevice.HEADPHONES)
@@ -135,7 +148,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
}
});
-var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
+export class AudioDeviceSelectionDBus {
constructor() {
this._audioSelectionDialog = null;
diff --git a/js/ui/background.js b/js/ui/background.js
index f5e7b1291..db6fde567 100644
--- a/js/ui/background.js
+++ b/js/ui/background.js
@@ -94,15 +94,22 @@
// MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage
-const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi;
-const Signals = imports.misc.signals;
+import Clutter from 'gi://Clutter';
+import GDesktopEnums from 'gi://GDesktopEnums';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import GnomeDesktop from 'gi://GnomeDesktop';
+import Meta from 'gi://Meta';
-const LoginManager = imports.misc.loginManager;
-const Main = imports.ui.main;
+import * as Signals from '../misc/signals.js';
+
+import * as LoginManager from '../misc/loginManager.js';
+import Main from './main.js';
Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
-var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
+export const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
const BACKGROUND_SCHEMA = 'org.gnome.desktop.background';
const PRIMARY_COLOR_KEY = 'primary-color';
@@ -111,14 +118,14 @@ const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_URI_KEY = 'picture-uri';
-var FADE_ANIMATION_TIME = 1000;
+export let FADE_ANIMATION_TIME = 1000;
-// These parameters affect how often we redraw.
-// The first is how different (percent crossfaded) the slide show
-// has to look before redrawing and the second is the minimum
-// frequency (in seconds) we're willing to wake up
-var ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
-var ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
+ // These parameters affect how often we redraw.
+ // The first is how different (percent crossfaded) the slide show
+ // has to look before redrawing and the second is the minimum
+ // frequency (in seconds) we're willing to wake up
+export let ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
+export let ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
let _backgroundCache = null;
@@ -132,12 +139,13 @@ function _fileEqual0(file1, file2) {
return file1.equal(file2);
}
-var BackgroundCache = class BackgroundCache extends Signals.EventEmitter {
+export class BackgroundCache extends Signals.EventEmitter {
constructor() {
super();
this._fileMonitors = {};
this._backgroundSources = {};
+ /** @type {{ [key: string]: Animation["prototype"] }} */
this._animations = {};
}
@@ -159,6 +167,16 @@ var BackgroundCache = class BackgroundCache extends Signals.EventEmitter {
this._fileMonitors[key] = monitor;
}
+ /**
+ * @typedef {object} AnimationParams
+ * @property {Gio.File} file
+ * @property {string} settingsSchema
+ * @property {((animation: Animation["prototype"]) => void) | null} onLoaded
+ */
+
+ /**
+ * @param {Partial<AnimationParams>} [params]
+ */
getAnimation(params = {}) {
const {
file = null,
@@ -219,13 +237,13 @@ var BackgroundCache = class BackgroundCache extends Signals.EventEmitter {
}
};
-function getBackgroundCache() {
+export function getBackgroundCache() {
if (!_backgroundCache)
_backgroundCache = new BackgroundCache();
return _backgroundCache;
}
-var Background = GObject.registerClass({
+export const Background = GObject.registerClass({
Signals: { 'loaded': {}, 'bg-changed': {} },
}, class Background extends Meta.Background {
_init(params = {}) {
@@ -248,6 +266,8 @@ var Background = GObject.registerClass({
this._cancellable = new Gio.Cancellable();
this.isLoaded = false;
+ this._changedId = -1;
+
this._clock = new GnomeDesktop.WallClock();
this._timezoneChangedId = this._clock.connect('notify::timezone',
() => {
@@ -269,6 +289,17 @@ var Background = GObject.registerClass({
this._load();
}
+ /**
+ * @param {(background: Background) => void} callback
+ */
+ onNextChange(callback) {
+ this._changedId = this.connect('bg-changed', (background) => {
+ background.disconnect(this._changedId);
+
+ callback(background);
+ });
+ }
+
destroy() {
this._cancellable.cancel();
this._removeAnimationTimeout();
@@ -515,7 +546,7 @@ var Background = GObject.registerClass({
let _systemBackground;
-var SystemBackground = GObject.registerClass({
+export const SystemBackground = GObject.registerClass({
Signals: { 'loaded': {} },
}, class SystemBackground extends Meta.BackgroundActor {
_init() {
@@ -538,7 +569,7 @@ var SystemBackground = GObject.registerClass({
}
});
-var BackgroundSource = class BackgroundSource {
+export class BackgroundSource {
constructor(layoutManager, settingsSchema) {
// Allow override the background image setting for performance testing
this._layoutManager = layoutManager;
@@ -601,9 +632,9 @@ var BackgroundSource = class BackgroundSource {
style,
});
- background._changedId = background.connect('bg-changed', () => {
- background.disconnect(background._changedId);
- background.destroy();
+ background.onNextChange((bg) => {
+ bg.destroy();
+
delete this._backgrounds[monitorIndex];
});
@@ -627,8 +658,11 @@ var BackgroundSource = class BackgroundSource {
}
};
-var Animation = GObject.registerClass(
+export const Animation = GObject.registerClass(
class Animation extends GnomeDesktop.BGSlideShow {
+ /**
+ * @param {*} params
+ */
_init(params) {
super._init(params);
@@ -638,6 +672,16 @@ class Animation extends GnomeDesktop.BGSlideShow {
this.loaded = false;
}
+ /**
+ * @returns {false}
+ */
+ load() {
+ throw new GObject.NotImplementedError(`Animation.prototype.load is not supported. Use loadAsync.`);
+ }
+
+ /**
+ * @param {() => void} callback
+ */
loadAsync(callback) {
this.load_async(null, () => {
this.loaded = true;
@@ -666,7 +710,7 @@ class Animation extends GnomeDesktop.BGSlideShow {
}
});
-var BackgroundManager = class BackgroundManager extends Signals.EventEmitter {
+export class BackgroundManager extends Signals.EventEmitter {
constructor(params = {}) {
super();
@@ -746,7 +790,7 @@ var BackgroundManager = class BackgroundManager extends Signals.EventEmitter {
const { background } = newBackgroundActor.content;
- if (background.isLoaded) {
+ if (background instanceof Background && background.isLoaded) {
this._swapBackgroundActor();
} else {
newBackgroundActor.loadedSignalId = background.connect('loaded',
diff --git a/js/ui/backgroundMenu.js b/js/ui/backgroundMenu.js
index e31e4c1a9..a311de559 100644
--- a/js/ui/backgroundMenu.js
+++ b/js/ui/backgroundMenu.js
@@ -1,13 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addBackgroundMenu */
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
-const BoxPointer = imports.ui.boxpointer;
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
+import * as BoxPointer from './boxpointer.js';
+import Main from './main.js';
+import * as PopupMenu from './popupMenu.js';
-var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
+export class BackgroundMenu extends PopupMenu.PopupMenu {
constructor(layoutManager) {
super(layoutManager.dummyCursor, 0, St.Side.TOP);
@@ -23,7 +24,7 @@ var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
}
};
-function addBackgroundMenu(actor, layoutManager) {
+export function addBackgroundMenu(actor, layoutManager) {
actor.reactive = true;
actor._backgroundMenu = new BackgroundMenu(layoutManager);
actor._backgroundManager = new PopupMenu.PopupMenuManager(actor);
diff --git a/js/ui/barLevel.js b/js/ui/barLevel.js
index 25d483528..ebf3171cc 100644
--- a/js/ui/barLevel.js
+++ b/js/ui/barLevel.js
@@ -1,9 +1,13 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported BarLevel */
-const { Atk, Clutter, GObject, St } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-var BarLevel = GObject.registerClass({
+
+export const BarLevel = GObject.registerClass({
Properties: {
'value': GObject.ParamSpec.double(
'value', 'value', 'value',
@@ -19,6 +23,9 @@ var BarLevel = GObject.registerClass({
1, 2, 1),
},
}, class BarLevel extends St.DrawingArea {
+ /**
+ * @param {*} params
+ */
_init(params) {
this._maxValue = 1;
this._value = 0;
diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js
index be9c57ce0..f10ae9933 100644
--- a/js/ui/boxpointer.js
+++ b/js/ui/boxpointer.js
@@ -1,18 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BoxPointer */
-const { Clutter, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const Main = imports.ui.main;
-var PopupAnimation = {
+import Main from './main.js';
+
+/** @enum {number} */
+export const PopupAnimation = {
NONE: 0,
SLIDE: 1 << 0,
FADE: 1 << 1,
FULL: ~0,
};
-var POPUP_ANIMATION_TIME = 150;
+export let POPUP_ANIMATION_TIME = 150;
/**
* BoxPointer:
@@ -27,9 +32,13 @@ var POPUP_ANIMATION_TIME = 150;
* totally inside the monitor workarea if possible.
*
*/
-var BoxPointer = GObject.registerClass({
+export const BoxPointer = GObject.registerClass({
Signals: { 'arrow-side-changed': {} },
}, class BoxPointer extends St.Widget {
+ /**
+ * @param {*} arrowSide
+ * @param {*} binProperties
+ */
_init(arrowSide, binProperties) {
super._init();
@@ -167,6 +176,12 @@ var BoxPointer = GObject.registerClass({
});
}
+ /**
+ * @param {boolean} isWidth
+ * @param {number} minSize
+ * @param {number} natSize
+ * @returns {[number, number]}
+ */
_adjustAllocationForArrow(isWidth, minSize, natSize) {
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
@@ -182,6 +197,9 @@ var BoxPointer = GObject.registerClass({
return [minSize, natSize];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
forHeight = themeNode.adjust_for_height(forHeight);
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index b3eb21dc8..31eef25bf 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -1,23 +1,28 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList, DBusEventSource */
-const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Main = imports.ui.main;
-const MessageList = imports.ui.messageList;
-const MessageTray = imports.ui.messageTray;
-const Mpris = imports.ui.mpris;
-const PopupMenu = imports.ui.popupMenu;
-const Util = imports.misc.util;
+import Main from './main.js';
+import * as MessageList from './messageList.js';
+import * as MessageTray from './messageTray.js';
+import * as Mpris from './mpris.js';
+import * as PopupMenu from './popupMenu.js';
+import * as Util from '../misc/util.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
-var MSECS_IN_DAY = 24 * 60 * 60 * 1000;
-var SHOW_WEEKDATE_KEY = 'show-weekdate';
+const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
+const SHOW_WEEKDATE_KEY = 'show-weekdate';
-var MESSAGE_ICON_SIZE = -1; // pick up from CSS
+export let MESSAGE_ICON_SIZE = -1; // pick up from CSS
-var NC_ = (context, str) => '%s\u0004%s'.format(context, str);
+export const NC_ = (context, str) => '%s\u0004%s'.format(context, str);
function sameYear(dateA, dateB) {
return dateA.getYear() == dateB.getYear();
@@ -81,7 +86,7 @@ function _getCalendarDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar
-var CalendarEvent = class CalendarEvent {
+export class CalendarEvent {
constructor(id, date, end, summary, allDay) {
this.id = id;
this.date = date;
@@ -94,7 +99,7 @@ var CalendarEvent = class CalendarEvent {
// Interface for appointments/events - e.g. the contents of a calendar
//
-var EventSourceBase = GObject.registerClass({
+export const EventSourceBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'has-calendars': GObject.ParamSpec.boolean(
@@ -108,10 +113,16 @@ var EventSourceBase = GObject.registerClass({
},
Signals: { 'changed': {} },
}, class EventSourceBase extends GObject.Object {
+ /**
+ * @returns {boolean}
+ */
get isLoading() {
throw new GObject.NotImplementedError('isLoading in %s'.format(this.constructor.name));
}
+ /**
+ * @returns {boolean}
+ */
get hasCalendars() {
throw new GObject.NotImplementedError('hasCalendars in %s'.format(this.constructor.name));
}
@@ -123,16 +134,22 @@ var EventSourceBase = GObject.registerClass({
throw new GObject.NotImplementedError('requestRange in %s'.format(this.constructor.name));
}
+ /**
+ * @returns {any[]}
+ */
getEvents(_begin, _end) {
throw new GObject.NotImplementedError('getEvents in %s'.format(this.constructor.name));
}
+ /**
+ * @returns {boolean}
+ */
hasEvents(_day) {
throw new GObject.NotImplementedError('hasEvents in %s'.format(this.constructor.name));
}
});
-var EmptyEventSource = GObject.registerClass(
+export const EmptyEventSource = GObject.registerClass(
class EmptyEventSource extends EventSourceBase {
get isLoading() {
return false;
@@ -185,7 +202,7 @@ function _dateIntervalsOverlap(a0, a1, b0, b1) {
}
// an implementation that reads data from a session bus service
-var DBusEventSource = GObject.registerClass(
+export const DBusEventSource = GObject.registerClass(
class DBusEventSource extends EventSourceBase {
_init() {
super._init();
@@ -373,9 +390,11 @@ class DBusEventSource extends EventSourceBase {
}
});
-var Calendar = GObject.registerClass({
+export const Calendar = GObject.registerClass({
Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } },
-}, class Calendar extends St.Widget {
+},
+/** @extends {St.Widget<Clutter.GridLayout>} */
+class Calendar extends St.Widget {
_init() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
@@ -719,7 +738,7 @@ var Calendar = GObject.registerClass({
}
});
-var NotificationMessage = GObject.registerClass(
+export const NotificationMessage = GObject.registerClass(
class NotificationMessage extends MessageList.Message {
_init(notification) {
super._init(notification.title, notification.bannerBodyText);
@@ -784,7 +803,7 @@ class NotificationMessage extends MessageList.Message {
}
});
-var TimeLabel = GObject.registerClass(
+export const TimeLabel = GObject.registerClass(
class NotificationTimeLabel extends St.Label {
_init(datetime) {
super._init({
@@ -801,7 +820,7 @@ class NotificationTimeLabel extends St.Label {
}
});
-var NotificationSection = GObject.registerClass(
+export const NotificationSection = GObject.registerClass(
class NotificationSection extends MessageList.MessageListSection {
_init() {
super._init();
@@ -882,7 +901,7 @@ class NotificationSection extends MessageList.MessageListSection {
}
});
-var Placeholder = GObject.registerClass(
+export const Placeholder = GObject.registerClass(
class Placeholder extends St.BoxLayout {
_init() {
super._init({ style_class: 'message-list-placeholder', vertical: true });
@@ -918,7 +937,7 @@ class DoNotDisturbSwitch extends PopupMenu.Switch {
}
});
-var CalendarMessageList = GObject.registerClass(
+export const CalendarMessageList = GObject.registerClass(
class CalendarMessageList extends St.Widget {
_init() {
super._init({
@@ -982,6 +1001,7 @@ class CalendarMessageList extends St.Widget {
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
+ /** @type {St.BoxLayout<MessageList.MessageListSection["prototype"]>} */
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true,
x_expand: true,
diff --git a/js/ui/checkBox.js b/js/ui/checkBox.js
index d64bd0d6c..4e227f618 100644
--- a/js/ui/checkBox.js
+++ b/js/ui/checkBox.js
@@ -1,7 +1,12 @@
/* exported CheckBox */
-const { Atk, Clutter, GObject, Pango, St } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Pango from 'gi://Pango';
+import St from 'gi://St';
-var CheckBox = GObject.registerClass(
+
+export const CheckBox = GObject.registerClass(
class CheckBox extends St.Button {
_init(label) {
let container = new St.BoxLayout({
diff --git a/js/ui/closeDialog.js b/js/ui/closeDialog.js
index 63a0bcfcf..8b66edf09 100644
--- a/js/ui/closeDialog.js
+++ b/js/ui/closeDialog.js
@@ -1,21 +1,30 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
-const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-var FROZEN_WINDOW_BRIGHTNESS = -0.3;
-var DIALOG_TRANSITION_TIME = 150;
-var ALIVE_TIMEOUT = 5000;
+import * as Dialog from './dialog.js';
+import Main from './main.js';
-var CloseDialog = GObject.registerClass({
+export let FROZEN_WINDOW_BRIGHTNESS = -0.3;
+export let DIALOG_TRANSITION_TIME = 150;
+export let ALIVE_TIMEOUT = 5000;
+
+export const CloseDialog = GObject.registerClass({
Implements: [Meta.CloseDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog),
},
}, class CloseDialog extends GObject.Object {
+ /**
+ * @param {Meta.Window} window
+ */
_init(window) {
super._init();
this._window = window;
@@ -30,6 +39,9 @@ var CloseDialog = GObject.registerClass({
return this._window;
}
+ /**
+ * @param {Meta.Window} window
+ */
set window(window) {
this._window = window;
}
@@ -61,6 +73,7 @@ var CloseDialog = GObject.registerClass({
if (this._dialog)
return;
+ /** @type {Meta.WindowActor} */
let windowActor = this._window.get_compositor_private();
this._dialog = new Dialog.Dialog(windowActor, 'close-dialog');
this._dialog.width = windowActor.width;
@@ -86,6 +99,7 @@ var CloseDialog = GObject.registerClass({
// We set the effect on the surface actor, so the dialog itself
// (which is a child of the MetaWindowActor) does not get the
// effect applied itself.
+ /** @type {Meta.WindowActor} */
let windowActor = this._window.get_compositor_private();
let surfaceActor = windowActor.get_first_child();
let effect = new Clutter.BrightnessContrastEffect();
@@ -94,15 +108,22 @@ var CloseDialog = GObject.registerClass({
}
_removeWindowEffect() {
+ /** @type {Meta.WindowActor} */
let windowActor = this._window.get_compositor_private();
let surfaceActor = windowActor.get_first_child();
surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
}
+ /**
+ * @this {Meta.CloseDialog}
+ */
_onWait() {
this.response(Meta.CloseDialogResponse.WAIT);
}
+ /**
+ * @this {Meta.CloseDialog}
+ */
_onClose() {
this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
}
diff --git a/js/ui/components/__init__.js b/js/ui/components.js
index 74300136b..db41db370 100644
--- a/js/ui/components/__init__.js
+++ b/js/ui/components.js
@@ -1,7 +1,7 @@
/* exported ComponentManager */
-const Main = imports.ui.main;
+import Main from './main.js';
-var ComponentManager = class {
+export class ComponentManager {
constructor() {
this._allComponents = {};
this._enabledComponents = [];
@@ -10,12 +10,12 @@ var ComponentManager = class {
this._sessionUpdated();
}
- _sessionUpdated() {
+ async _sessionUpdated() {
let newEnabledComponents = Main.sessionMode.components;
- newEnabledComponents
+ await Promise.all([...newEnabledComponents
.filter(name => !this._enabledComponents.includes(name))
- .forEach(name => this._enableComponent(name));
+ .map(name => this._enableComponent(name))]);
this._enabledComponents
.filter(name => !newEnabledComponents.includes(name))
@@ -24,12 +24,12 @@ var ComponentManager = class {
this._enabledComponents = newEnabledComponents;
}
- _importComponent(name) {
- let module = imports.ui.components[name];
+ async _importComponent(name) {
+ let module = await import(`./components/${name}.js`);
return module.Component;
}
- _ensureComponent(name) {
+ async _ensureComponent(name) {
let component = this._allComponents[name];
if (component)
return component;
@@ -37,14 +37,14 @@ var ComponentManager = class {
if (Main.sessionMode.isLocked)
return null;
- let constructor = this._importComponent(name);
+ let constructor = await this._importComponent(name);
component = new constructor();
this._allComponents[name] = component;
return component;
}
- _enableComponent(name) {
- let component = this._ensureComponent(name);
+ async _enableComponent(name) {
+ let component = await this._ensureComponent(name);
if (component)
component.enable();
}
diff --git a/js/ui/components/automountManager.js b/js/ui/components/automountManager.js
index ecf9fa144..7cd273501 100644
--- a/js/ui/components/automountManager.js
+++ b/js/ui/components/automountManager.js
@@ -1,25 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Gio, GLib } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
-const GnomeSession = imports.misc.gnomeSession;
-const Main = imports.ui.main;
-const ShellMountOperation = imports.ui.shellMountOperation;
+import * as GnomeSession from '../../misc/gnomeSession.js';
+import Main from './../main.js';
+import * as ShellMountOperation from './../shellMountOperation.js';
-var GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
+export let GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
// GSettings keys
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
const SETTING_ENABLE_AUTOMOUNT = 'automount';
-var AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
+export let AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
-var AutomountManager = class {
+export class AutomountManager {
constructor() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._activeOperations = new Map();
- this._session = new GnomeSession.SessionManager();
+ this._session = GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded',
this._InhibitorsChanged.bind(this));
this._session.connectSignal('InhibitorRemoved',
@@ -130,6 +131,18 @@ var AutomountManager = class {
this._checkAndMountVolume(volume);
}
+ /**
+ * @typedef {object} VolumeMountProps: An object with the properties:
+ * @property {boolean} [checkSession]
+ * @property {boolean} [useMountOp]
+ * @property {boolean} [allowAutorun]
+ */
+
+ /**
+ * _checkAndMountVolume:
+ * @param {Gio.Volume} volume
+ * @param {Partial<VolumeMountProps>} [params]
+ */
_checkAndMountVolume(volume, params = {}) {
const {
checkSession = true,
@@ -253,4 +266,4 @@ var AutomountManager = class {
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
}
};
-var Component = AutomountManager;
+export let Component = AutomountManager;
diff --git a/js/ui/components/autorunManager.js b/js/ui/components/autorunManager.js
index 16b52cfe3..6b321f3e9 100644
--- a/js/ui/components/autorunManager.js
+++ b/js/ui/components/autorunManager.js
@@ -1,13 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Clutter, Gio, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const GnomeSession = imports.misc.gnomeSession;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import * as GnomeSession from '../../misc/gnomeSession.js';
+import Main from './../main.js';
+import * as MessageTray from './../messageTray.js';
+
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
// GSettings keys
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
@@ -16,7 +20,8 @@ const SETTING_START_APP = 'autorun-x-content-start-app';
const SETTING_IGNORE = 'autorun-x-content-ignore';
const SETTING_OPEN_FOLDER = 'autorun-x-content-open-folder';
-var AutorunSetting = {
+/** @enum {number} */
+export const AutorunSetting = {
RUN: 0,
IGNORE: 1,
FILES: 2,
@@ -80,7 +85,7 @@ function HotplugSniffer() {
'/org/gnome/Shell/HotplugSniffer');
}
-var ContentTypeDiscoverer = class {
+export class ContentTypeDiscoverer {
constructor(callback) {
this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
@@ -142,9 +147,9 @@ var ContentTypeDiscoverer = class {
}
};
-var AutorunManager = class {
+export class AutorunManager {
constructor() {
- this._session = new GnomeSession.SessionManager();
+ this._session = GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this);
@@ -160,7 +165,10 @@ var AutorunManager = class {
this._volumeMonitor.disconnect(this._mountRemovedId);
}
- _onMountAdded(monitor, mount) {
+ /**
+ * @param {Gio.Mount} mount
+ */
+ _onMountAdded(_, mount) {
// don't do anything if our session is not the currently
// active one
if (!this._session.SessionIsActive)
@@ -177,7 +185,10 @@ var AutorunManager = class {
}
};
-var AutorunDispatcher = class {
+export class AutorunDispatcher {
+ /**
+ * @param {AutorunManager} manager
+ */
constructor(manager) {
this._manager = manager;
this._sources = [];
@@ -212,6 +223,10 @@ var AutorunDispatcher = class {
return null;
}
+ /**
+ * @param {Gio.Mount} mount
+ * @param {Gio.Application[]} apps
+ */
_addSource(mount, apps) {
// if we already have a source showing for this
// mount, return
@@ -222,6 +237,10 @@ var AutorunDispatcher = class {
this._sources.push(new AutorunSource(this._manager, mount, apps));
}
+ /**
+ * @param {Gio.Mount} mount
+ * @param {Gio.Application[]} apps
+ */
addMount(mount, apps, contentTypes) {
// if autorun is disabled globally, return
if (this._settings.get_boolean(SETTING_DISABLE_AUTORUN))
@@ -271,7 +290,14 @@ var AutorunDispatcher = class {
}
};
-var AutorunSource = GObject.registerClass(
+/**
+ * @typedef {object} AutorunSourceParams
+ * @property {AutorunManager} manager
+ * @property {Gio.Mount} mount
+ * @property {Gio.Application[]} apps
+ */
+
+export const AutorunSource = GObject.registerClass(
class AutorunSource extends MessageTray.Source {
_init(manager, mount, apps) {
super._init(mount.get_name());
@@ -296,8 +322,12 @@ class AutorunSource extends MessageTray.Source {
}
});
-var AutorunNotification = GObject.registerClass(
+export const AutorunNotification = GObject.registerClass(
class AutorunNotification extends MessageTray.Notification {
+ /**
+ * @param {*} manager
+ * @param {*} source
+ */
_init(manager, source) {
super._init(source, source.title);
@@ -356,4 +386,4 @@ class AutorunNotification extends MessageTray.Notification {
}
});
-var Component = AutorunManager;
+export let Component = AutorunManager;
diff --git a/js/ui/components/keyring.js b/js/ui/components/keyring.js
index cd7a81e95..08f17a5fa 100644
--- a/js/ui/components/keyring.js
+++ b/js/ui/components/keyring.js
@@ -1,15 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const ModalDialog = imports.ui.modalDialog;
-const ShellEntry = imports.ui.shellEntry;
-const CheckBox = imports.ui.checkBox;
-const Util = imports.misc.util;
-
-var KeyringDialog = GObject.registerClass(
+import Clutter from 'gi://Clutter';
+import Gcr from 'gi://Gcr';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+
+import * as Dialog from './../dialog.js';
+import * as ModalDialog from './../modalDialog.js';
+import * as ShellEntry from './../shellEntry.js';
+import * as CheckBox from './../checkBox.js';
+import * as Util from '../../misc/util.js';
+
+export const KeyringDialog = GObject.registerClass(
class KeyringDialog extends ModalDialog.ModalDialog {
_init() {
super._init({ styleClass: 'prompt-dialog' });
@@ -178,7 +185,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
}
});
-var KeyringDummyDialog = class {
+export class KeyringDummyDialog {
constructor() {
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
@@ -190,7 +197,7 @@ var KeyringDummyDialog = class {
}
};
-var KeyringPrompter = GObject.registerClass(
+export const KeyringPrompter = GObject.registerClass(
class KeyringPrompter extends Gcr.SystemPrompter {
_init() {
super._init();
@@ -226,4 +233,4 @@ class KeyringPrompter extends Gcr.SystemPrompter {
}
});
-var Component = KeyringPrompter;
+export let Component = KeyringPrompter;
diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js
index 367deb666..5c5000475 100644
--- a/js/ui/components/networkAgent.js
+++ b/js/ui/components/networkAgent.js
@@ -1,14 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const ModalDialog = imports.ui.modalDialog;
-const ShellEntry = imports.ui.shellEntry;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import NM from 'gi://NM';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../../misc/signals.js';
+
+import * as Dialog from './../dialog.js';
+import Main from './../main.js';
+import * as MessageTray from './../messageTray.js';
+import * as ModalDialog from './../modalDialog.js';
+import * as ShellEntry from './../shellEntry.js';
Gio._promisify(Shell.NetworkAgent.prototype, 'init_async', 'init_finish');
Gio._promisify(Shell.NetworkAgent.prototype,
@@ -16,11 +23,21 @@ Gio._promisify(Shell.NetworkAgent.prototype,
const VPN_UI_GROUP = 'VPN Plugin UI';
-var NetworkSecretDialog = GObject.registerClass(
+export const NetworkSecretDialog = GObject.registerClass(
class NetworkSecretDialog extends ModalDialog.ModalDialog {
+ /**
+ * @param {any | Shell.NetworkAgent} agent
+ * @param {string} requestId
+ * @param {NM.Connection} connection
+ * @param {string} settingName
+ * @param {string[]} hints
+ * @param {number} flags
+ * @param {{ title: string, message: string, secrets: string[] }} [contentOverride]
+ */
_init(agent, requestId, connection, settingName, hints, flags, contentOverride) {
super._init({ styleClass: 'prompt-dialog' });
+ /** @type {Shell.NetworkAgent} */
this._agent = agent;
this._requestId = requestId;
this._connection = connection;
@@ -213,7 +230,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
case 'none': // static WEP
secrets.push({
label: _('Key'),
- key: 'wep-key%s'.format(wirelessSecuritySetting.wep_tx_keyidx),
+ key: 'wep-key%s'.format(wirelessSecuritySetting.wep_tx_keyidx.toFixed(0)),
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
wep_key_type: wirelessSecuritySetting.wep_key_type,
validate: this._validateStaticWep,
@@ -298,7 +315,8 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
else
setting = this._connection.get_setting_by_name(connectionType);
secrets.push({ label: _('Password'), key: 'password',
- value: setting.value || '', password: true });
+ // TODO: Does not exist: setting.value on NM.Setting
+ value: '', password: true });
}
_getContent() {
@@ -354,7 +372,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
}
});
-var VPNRequestHandler = class extends Signals.EventEmitter {
+export class VPNRequestHandler extends Signals.EventEmitter {
constructor(agent, requestId, authHelper, serviceType, connection, hints, flags) {
super();
@@ -527,7 +545,6 @@ var VPNRequestHandler = class extends Signals.EventEmitter {
let keyfile = new GLib.KeyFile();
let data;
let contentOverride;
-
try {
data = new GLib.Bytes(this._dataStdout.peek_buffer());
keyfile.load_from_bytes(data, GLib.KeyFileFlags.NONE);
@@ -563,7 +580,7 @@ var VPNRequestHandler = class extends Signals.EventEmitter {
}
} catch (e) {
// No output is a valid case it means "both secrets are stored"
- if (data.length > 0) {
+ if (data.get_size() > 0) {
logError(e, 'error while reading VPN plugin output keyfile');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
@@ -604,7 +621,7 @@ var VPNRequestHandler = class extends Signals.EventEmitter {
}
};
-var NetworkAgent = class {
+export class NetworkAgent {
constructor() {
this._native = new Shell.NetworkAgent({
identifier: 'org.gnome.Shell.NetworkAgent',
@@ -807,4 +824,4 @@ var NetworkAgent = class {
};
}
};
-var Component = NetworkAgent;
+export let Component = NetworkAgent;
diff --git a/js/ui/components/polkitAgent.js b/js/ui/components/polkitAgent.js
index 5127ab924..ad7120678 100644
--- a/js/ui/components/polkitAgent.js
+++ b/js/ui/components/polkitAgent.js
@@ -1,16 +1,25 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { AccountsService, Clutter, GLib,
- GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
-const ShellEntry = imports.ui.shellEntry;
-const UserWidget = imports.ui.userWidget;
-const Util = imports.misc.util;
-
+import AccountsService from 'gi://AccountsService';
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Pango from 'gi://Pango';
+import PolkitAgent from 'gi://PolkitAgent';
+import Polkit from 'gi://Polkit';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+
+import * as Dialog from './../dialog.js';
+import Main from './../main.js';
+import * as ModalDialog from './../modalDialog.js';
+import * as ShellEntry from './../shellEntry.js';
+import * as UserWidget from './../userWidget.js';
+import * as Util from '../../misc/util.js';
+
+/** @enum {number} */
const DialogMode = {
AUTH: 0,
CONFIRM: 1,
@@ -20,9 +29,15 @@ const DIALOG_ICON_SIZE = 64;
const DELAYED_RESET_TIMEOUT = 200;
-var AuthenticationDialog = GObject.registerClass({
+export const AuthenticationDialog = GObject.registerClass({
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } },
}, class AuthenticationDialog extends ModalDialog.ModalDialog {
+ /**
+ * @param {*} actionId
+ * @param {*} description
+ * @param {*} cookie
+ * @param {*} userNames
+ */
_init(actionId, description, cookie, userNames) {
super._init({ styleClass: 'prompt-dialog' });
@@ -410,7 +425,7 @@ var AuthenticationDialog = GObject.registerClass({
}
});
-var AuthenticationAgent = GObject.registerClass(
+export const AuthenticationAgent = GObject.registerClass(
class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
_init() {
super._init();
@@ -473,4 +488,4 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
}
});
-var Component = AuthenticationAgent;
+export let Component = AuthenticationAgent;
diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js
index 3d7020041..fc8fb31b6 100644
--- a/js/ui/components/telepathyClient.js
+++ b/js/ui/components/telepathyClient.js
@@ -1,12 +1,29 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Clutter, Gio, GLib, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
+
+import gi from 'gi';
+
+import Main from './../main.js';
+
+import * as History from '../../misc/history.js';
+import * as MessageList from './../messageList.js';
+import * as MessageTray from './../messageTray.js';
+import * as Util from '../../misc/util.js';
+
+/** @type {import('telepathylogger0')} */
+let Tpl = null;
+/** @type {import('telepathyglib0')} */
+let Tp = null;
-var Tpl = null;
-var Tp = null;
try {
- ({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
+ Tp = gi.require('TelepathyGlib');
+ Tpl = gi.require('TelepathyLogger');
Gio._promisify(Tp.Channel.prototype, 'close_async', 'close_finish');
Gio._promisify(Tp.TextChannel.prototype,
@@ -19,29 +36,23 @@ try {
log('Telepathy is not available, chat integration will be disabled.');
}
-const History = imports.misc.history;
-const Main = imports.ui.main;
-const MessageList = imports.ui.messageList;
-const MessageTray = imports.ui.messageTray;
-const Util = imports.misc.util;
-
const HAVE_TP = Tp != null && Tpl != null;
// See Notification.appendMessage
-var SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes
-var SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
-var SCROLLBACK_RECENT_LENGTH = 20;
-var SCROLLBACK_IDLE_LENGTH = 5;
+export let SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes
+export let SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
+export let SCROLLBACK_RECENT_LENGTH = 20;
+export let SCROLLBACK_IDLE_LENGTH = 5;
// See Source._displayPendingMessages
-var SCROLLBACK_HISTORY_LINES = 10;
+export let SCROLLBACK_HISTORY_LINES = 10;
// See Notification._onEntryChanged
-var COMPOSING_STOP_TIMEOUT = 5;
+export let COMPOSING_STOP_TIMEOUT = 5;
-var CHAT_EXPAND_LINES = 12;
+export let CHAT_EXPAND_LINES = 12;
-var NotificationDirection = {
+export const NotificationDirection = {
SENT: 'chat-sent',
RECEIVED: 'chat-received',
};
@@ -51,8 +62,8 @@ const ChatMessage = HAVE_TP ? GObject.registerClass({
'message-type': GObject.ParamSpec.int(
'message-type', 'message-type', 'message-type',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
- Math.min(...Object.values(Tp.ChannelTextMessageType)),
- Math.max(...Object.values(Tp.ChannelTextMessageType)),
+ Tp.ChannelTextMessageType.NORMAL,
+ Tp.ChannelTextMessageType.DELIVERY_REPORT,
Tp.ChannelTextMessageType.NORMAL),
'text': GObject.ParamSpec.string(
'text', 'text', 'text',
@@ -71,35 +82,52 @@ const ChatMessage = HAVE_TP ? GObject.registerClass({
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
},
-}, class ChatMessageClass extends GObject.Object {
- static newFromTpMessage(tpMessage, direction) {
- return new ChatMessage({
- 'message-type': tpMessage.get_message_type(),
- 'text': tpMessage.to_text()[0],
- 'sender': tpMessage.sender.alias,
- 'timestamp': direction === NotificationDirection.RECEIVED
- ? tpMessage.get_received_timestamp() : tpMessage.get_sent_timestamp(),
- direction,
- });
- }
-
- static newFromTplTextEvent(tplTextEvent) {
- let direction =
- tplTextEvent.get_sender().get_entity_type() === Tpl.EntityType.SELF
- ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
-
- return new ChatMessage({
- 'message-type': tplTextEvent.get_message_type(),
- 'text': tplTextEvent.get_message(),
- 'sender': tplTextEvent.get_sender().get_alias(),
- 'timestamp': tplTextEvent.get_timestamp(),
- direction,
- });
+}, class ChatMessage extends GObject.Object {
+ /**
+ * @param {{ [key: string]: any }} properties
+ */
+ _init(properties) {
+ super._init(properties);
+
+ /** @type {number} */
+ this.messageType;
+ /** @type {string} */
+ this.text;
+ /** @type {string} */
+ this.sender;
+ /** @type {number} */
+ this.timestamp;
+ /** @type {string} */
+ this.direction ;
}
}) : null;
+function newChatMessageFromTpMessage(tpMessage, direction) {
+ return new ChatMessage({
+ 'message-type': tpMessage.get_message_type(),
+ 'text': tpMessage.to_text()[0],
+ 'sender': tpMessage.sender.alias,
+ 'timestamp': direction === NotificationDirection.RECEIVED
+ ? tpMessage.get_received_timestamp() : tpMessage.get_sent_timestamp(),
+ direction,
+ });
+}
+
+function newChatMessageFromTplTextEvent(tplTextEvent) {
+ let direction =
+ tplTextEvent.get_sender().get_entity_type() === Tpl.EntityType.SELF
+ ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
+
+ return new ChatMessage({
+ 'message-type': tplTextEvent.get_message_type(),
+ 'text': tplTextEvent.get_message(),
+ 'sender': tplTextEvent.get_sender().get_alias(),
+ 'timestamp': tplTextEvent.get_timestamp(),
+ direction,
+ });
+}
-var TelepathyComponent = class {
+export class TelepathyComponent {
constructor() {
this._client = null;
@@ -131,7 +159,7 @@ var TelepathyComponent = class {
}
};
-var TelepathyClient = HAVE_TP ? GObject.registerClass(
+export let TelepathyClient = HAVE_TP ? GObject.registerClass(
class TelepathyClient extends Tp.BaseClient {
_init() {
// channel path -> ChatSource
@@ -161,11 +189,12 @@ class TelepathyClient extends Tp.BaseClient {
uniquify_name: true });
// We only care about single-user text-based chats
- let filter = {};
- filter[Tp.PROP_CHANNEL_CHANNEL_TYPE] = Tp.IFACE_CHANNEL_TYPE_TEXT;
- filter[Tp.PROP_CHANNEL_TARGET_HANDLE_TYPE] = Tp.HandleType.CONTACT;
-
+ let filter = {
+ [Tp.PROP_CHANNEL_CHANNEL_TYPE] : Tp.IFACE_CHANNEL_TYPE_TEXT,
+ [Tp.PROP_CHANNEL_TARGET_HANDLE_TYPE] : Tp.HandleType.CONTACT,
+ };
this.set_observer_recover(true);
+ // FIXME
this.add_observer_filter(filter);
this.add_approver_filter(filter);
this.add_handler_filter(filter);
@@ -201,7 +230,7 @@ class TelepathyClient extends Tp.BaseClient {
if (this._chatSources[channel.get_object_path()])
return;
- let source = new ChatSource(account, conn, channel, contact, this);
+ let source = new ChatSource({ account, connection: conn, channel, contact, client: this });
this._chatSources[channel.get_object_path()] = source;
source.connect('destroy', () => {
@@ -294,19 +323,37 @@ class TelepathyClient extends Tp.BaseClient {
}
}) : null;
-var ChatSource = HAVE_TP ? GObject.registerClass(
+/**
+ * @typedef {object} ChatSourceParams
+ * @property {import('telepathyglib0').Account} account
+ * @property {import('telepathyglib0').Connection} connection
+ * @property {import('telepathyglib0').TextChannel} channel
+ * @property {import('telepathyglib0').Contact} contact
+ * @property {import('telepathyglib0').BaseClient} client
+ */
+
+export let ChatSource = HAVE_TP ? GObject.registerClass(
class ChatSource extends MessageTray.Source {
- _init(account, conn, channel, contact, client) {
+
+ /**
+ * @param {import('../messageTray.js').SourceParams & ChatSourceParams} params
+ */
+ _init(params) {
+ const { account, contact, client, connection, channel, ...sourceParams } = params;
+
this._account = account;
this._contact = contact;
this._client = client;
- super._init(contact.get_alias());
+ super._init({
+ title: contact.get_alias(),
+ ...sourceParams
+ });
this.isChat = true;
this._pendingMessages = [];
- this._conn = conn;
+ this._conn = connection;
this._channel = channel;
this._closedId = this._channel.connect('invalidated', this._channelClosed.bind(this));
@@ -455,7 +502,7 @@ class ChatSource extends MessageTray.Source {
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null);
- let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
+ let logMessages = events.map(e => newChatMessageFromTplTextEvent(e));
this._ensureNotification();
let pendingTpMessages = this._channel.get_pending_messages();
@@ -467,7 +514,7 @@ class ChatSource extends MessageTray.Source {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
continue;
- pendingMessages.push(ChatMessage.newFromTpMessage(message,
+ pendingMessages.push(newChatMessageFromTpMessage(message,
NotificationDirection.RECEIVED));
this._pendingMessages.push(message);
@@ -492,7 +539,7 @@ class ChatSource extends MessageTray.Source {
if (!isPending) {
showTimestamp = true;
- this._notification.appendMessage(logMessage, true, ['chat-log-message']);
+ this._notification.appendMessage(logMessage, true);
}
}
@@ -564,7 +611,7 @@ class ChatSource extends MessageTray.Source {
this._pendingMessages.push(message);
this.countUpdated();
- message = ChatMessage.newFromTpMessage(message,
+ message = newChatMessageFromTpMessage(message,
NotificationDirection.RECEIVED);
this._notification.appendMessage(message);
@@ -590,7 +637,7 @@ class ChatSource extends MessageTray.Source {
// our client and other clients as well.
_messageSent(channel, message, _flags, _token) {
this._ensureNotification();
- message = ChatMessage.newFromTpMessage(message,
+ message = newChatMessageFromTpMessage(message,
NotificationDirection.SENT);
this._notification.appendMessage(message);
}
@@ -655,19 +702,25 @@ class ChatSource extends MessageTray.Source {
const ChatNotificationMessage = HAVE_TP ? GObject.registerClass(
class ChatNotificationMessage extends GObject.Object {
+ /**
+ * @param {*} props
+ */
_init(props = {}) {
super._init();
this.set(props);
}
}) : null;
-var ChatNotification = HAVE_TP ? GObject.registerClass({
+export let ChatNotification = HAVE_TP ? GObject.registerClass({
Signals: {
'message-removed': { param_types: [ChatNotificationMessage.$gtype] },
'message-added': { param_types: [ChatNotificationMessage.$gtype] },
'timestamp-changed': { param_types: [ChatNotificationMessage.$gtype] },
},
}, class ChatNotification extends MessageTray.Notification {
+ /**
+ * @param {*} source
+ */
_init(source) {
super._init(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
@@ -687,18 +740,13 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
/**
* appendMessage:
- * @param {Object} message: An object with the properties
- * {string} message.text: the body of the message,
- * {Tp.ChannelTextMessageType} message.messageType: the type
- * {string} message.sender: the name of the sender,
- * {number} message.timestamp: the time the message was sent
- * {NotificationDirection} message.direction: a #NotificationDirection
+ * @param {ChatMessage["prototype"]} message: An object with the properties
*
- * @param {bool} noTimestamp: Whether to add a timestamp. If %true,
+ * @param {boolean} [noTimestamp]: Whether to add a timestamp. If %true,
* no timestamp will be added, regardless of the difference since
* the last timestamp
*/
- appendMessage(message, noTimestamp) {
+ appendMessage(message, noTimestamp = false) {
let messageBody = GLib.markup_escape_text(message.text, -1);
let styles = [message.direction];
@@ -714,11 +762,8 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
bannerMarkup: true });
}
- let group = message.direction == NotificationDirection.RECEIVED
- ? 'received' : 'sent';
-
this._append({ body: messageBody,
- group,
+ group: message.direction == NotificationDirection.RECEIVED ? 'received' : 'sent',
styles,
timestamp: message.timestamp,
noTimestamp });
@@ -749,15 +794,18 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
}
}
+ /**
+ * @typedef {object} AppendProps: An object with the properties:
+ * @property {string?} body: The text of the message.
+ * @property {('received' | 'sent' | 'meta')?} group: The group of the message, one of: 'received', 'sent', 'meta'.
+ * @property {string[]} [styles]: Style class names for the message to have.
+ * @property {number} [timestamp]: The timestamp of the message.
+ * @property {boolean} [noTimestamp]: suppress timestamp signal?
+ */
+
/**
* _append:
- * @param {Object} props: An object with the properties:
- * {string} props.body: The text of the message.
- * {string} props.group: The group of the message, one of:
- * 'received', 'sent', 'meta'.
- * {string[]} props.styles: Style class names for the message to have.
- * {number} props.timestamp: The timestamp of the message.
- * {bool} props.noTimestamp: suppress timestamp signal?
+ * @param {Partial<AppendProps>} props
*/
_append(props = {}) {
let currentTime = Date.now() / 1000;
@@ -828,16 +876,22 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
}
}) : null;
-var ChatLineBox = GObject.registerClass(
+export const ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(forWidth) {
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
return [natHeight, natHeight];
}
});
-var ChatNotificationBanner = GObject.registerClass(
+export const ChatNotificationBanner = GObject.registerClass(
class ChatNotificationBanner extends MessageTray.NotificationBanner {
+ /**
+ * @param {*} notification
+ */
_init(notification) {
super._init(notification);
@@ -1014,4 +1068,4 @@ class ChatNotificationBanner extends MessageTray.NotificationBanner {
}
});
-var Component = TelepathyComponent;
+export const Component = TelepathyComponent;
diff --git a/js/ui/ctrlAltTab.js b/js/ui/ctrlAltTab.js
index 6507886a4..3735964f9 100644
--- a/js/ui/ctrlAltTab.js
+++ b/js/ui/ctrlAltTab.js
@@ -1,20 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CtrlAltTabManager */
-const { Clutter, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Main = imports.ui.main;
-const SwitcherPopup = imports.ui.switcherPopup;
+import Main from './main.js';
+import * as SwitcherPopup from './switcherPopup.js';
-var POPUP_APPICON_SIZE = 96;
+export let POPUP_APPICON_SIZE = 96;
-var SortGroup = {
+export const SortGroup = {
TOP: 0,
MIDDLE: 1,
BOTTOM: 2,
};
-var CtrlAltTabManager = class CtrlAltTabManager {
+export class CtrlAltTabManager {
constructor() {
this._items = [];
this.addGroup(global.window_group, _("Windows"),
@@ -138,7 +142,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
}
};
-var CtrlAltTabPopup = GObject.registerClass(
+export const CtrlAltTabPopup = GObject.registerClass(
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
_init(items) {
super._init(items);
@@ -167,7 +171,7 @@ class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
}
});
-var CtrlAltTabSwitcher = GObject.registerClass(
+export const CtrlAltTabSwitcher = GObject.registerClass(
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
_init(items) {
super._init(true);
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 08902c436..6a083fad7 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -1,29 +1,34 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
-const { Clutter, GLib, GObject,
- Graphene, Meta, Shell, St } = imports.gi;
-
-const AppDisplay = imports.ui.appDisplay;
-const AppFavorites = imports.ui.appFavorites;
-const DND = imports.ui.dnd;
-const IconGrid = imports.ui.iconGrid;
-const Main = imports.ui.main;
-const Overview = imports.ui.overview;
-
-var DASH_ANIMATION_TIME = 200;
-var DASH_ITEM_LABEL_SHOW_TIME = 150;
-var DASH_ITEM_LABEL_HIDE_TIME = 100;
-var DASH_ITEM_HOVER_TIMEOUT = 300;
-
-function getAppFromSource(source) {
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Graphene from 'gi://Graphene';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AppDisplay from './appDisplay.js';
+import * as AppFavorites from './appFavorites.js';
+import * as DND from './dnd.js';
+import * as IconGrid from './iconGrid.js';
+import * as Overview from './overview.js';
+import Main from './main.js';
+
+export const DASH_ANIMATION_TIME = 200;
+export const DASH_ITEM_LABEL_SHOW_TIME = 150;
+export const DASH_ITEM_LABEL_HIDE_TIME = 100;
+export const DASH_ITEM_HOVER_TIMEOUT = 300;
+
+export function getAppFromSource(source) {
if (source instanceof AppDisplay.AppIcon)
return source.app;
else
return null;
}
-var DashIcon = GObject.registerClass(
+export const DashIcon = GObject.registerClass(
class DashIcon extends AppDisplay.AppIcon {
_init(app) {
super._init(app, {
@@ -54,7 +59,7 @@ class DashIcon extends AppDisplay.AppIcon {
// A container like StBin, but taking the child's scale into account
// when requesting a size
-var DashItemContainer = GObject.registerClass(
+export const DashItemContainer = GObject.registerClass(
class DashItemContainer extends St.Widget {
_init() {
super._init({
@@ -74,6 +79,7 @@ class DashItemContainer extends St.Widget {
Main.layoutManager.addChrome(this.label);
this.label_actor = this.label;
+ /** @type {St.Bin | null} */
this.child = null;
this.animatingOut = false;
@@ -146,6 +152,9 @@ class DashItemContainer extends St.Widget {
});
}
+ /**
+ * @param {St.Bin} actor
+ */
setChild(actor) {
if (this.child == actor)
return;
@@ -191,7 +200,7 @@ class DashItemContainer extends St.Widget {
}
});
-var ShowAppsIcon = GObject.registerClass(
+export const ShowAppsIcon = GObject.registerClass(
class ShowAppsIcon extends DashItemContainer {
_init() {
super._init();
@@ -270,7 +279,7 @@ class ShowAppsIcon extends DashItemContainer {
}
});
-var DragPlaceholderItem = GObject.registerClass(
+export const DragPlaceholderItem = GObject.registerClass(
class DragPlaceholderItem extends DashItemContainer {
_init() {
super._init();
@@ -278,7 +287,7 @@ class DragPlaceholderItem extends DashItemContainer {
}
});
-var EmptyDropTargetItem = GObject.registerClass(
+export const EmptyDropTargetItem = GObject.registerClass(
class EmptyDropTargetItem extends DashItemContainer {
_init() {
super._init();
@@ -294,6 +303,7 @@ class DashIconsLayout extends Clutter.BoxLayout {
});
}
+ /** @returns {[number, number]} */
vfunc_get_preferred_width(container, forHeight) {
const [, natWidth] = super.vfunc_get_preferred_width(container, forHeight);
return [0, natWidth];
@@ -302,7 +312,7 @@ class DashIconsLayout extends Clutter.BoxLayout {
const baseIconSizes = [16, 22, 24, 32, 48, 64];
-var Dash = GObject.registerClass({
+export const Dash = GObject.registerClass({
Signals: { 'icon-size-changed': {} },
}, class Dash extends St.Widget {
_init() {
@@ -330,6 +340,7 @@ var Dash = GObject.registerClass({
y_expand: true,
});
+ /** @type {St.Widget<DashIconsLayout["prototype"], Clutter.Content, St.Widget | DashItemContainer["prototype"]>} */
this._box = new St.Widget({
clip_to_allocation: true,
layout_manager: new DashIconsLayout(),
@@ -507,6 +518,10 @@ var Dash = GObject.registerClass({
});
let item = new DashItemContainer();
+
+ // TODO: I don't know why this type error is occuring.
+ // I'm guessing it is an issue with the complicated inheritance.
+ // @ts-expect-error
item.setChild(appIcon);
// Override default AppIcon label_actor, now the
@@ -574,9 +589,16 @@ var Dash = GObject.registerClass({
// icons (i.e. ignoring drag placeholders) and which are not
// animating out (which means they will be destroyed at the end of
// the animation)
- let iconChildren = this._box.get_children().filter(actor => {
- return actor.child &&
+ let iconChildren = this._box.get_children().filter(
+ /**
+ * @param {Clutter.Actor} actor
+ * @returns {actor is DashItemContainer["prototype"]}
+ */
+ (actor) => {
+ return actor instanceof DashItemContainer &&
+ actor.child &&
actor.child._delegate &&
+ // @ts-expect-error
actor.child._delegate.icon &&
!actor.animatingOut;
});
@@ -598,7 +620,7 @@ var Dash = GObject.registerClass({
let spacing = themeNode.get_length('spacing');
let firstButton = iconChildren[0].child;
- let firstIcon = firstButton._delegate.icon;
+ let firstIcon = /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (firstButton._delegate).icon;
// Enforce valid spacings during the size request
firstIcon.icon.ensure_style();
@@ -634,7 +656,7 @@ var Dash = GObject.registerClass({
let scale = oldIconSize / newIconSize;
for (let i = 0; i < iconChildren.length; i++) {
- let icon = iconChildren[i].child._delegate.icon;
+ let icon = /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (iconChildren[i].child._delegate).icon;
// Set the new size immediately, to keep the icons' sizes
// in sync with this.iconSize
@@ -676,13 +698,20 @@ var Dash = GObject.registerClass({
let running = this._appSystem.get_running();
+ // FIXME
let children = this._box.get_children().filter(actor => {
- return actor.child &&
- actor.child._delegate &&
- actor.child._delegate.app;
+ return 'child' in actor && actor.child &&
+ /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (actor.child._delegate).app &&
+ /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (actor.child._delegate).app;
+
});
// Apps currently in the dash
- let oldApps = children.map(actor => actor.child._delegate.app);
+ let oldApps = children.map(actor => 'child' in actor ? actor.child._delegate : null).filter(
+ /**
+ * @param {unknown} delegate '
+ * @returns {delegate is typeof AppDisplay.AppIcon["prototype"]}
+ */
+ delegate => delegate instanceof AppDisplay.AppIcon).map(d => d.app);
// Apps supposed to be in the dash
let newApps = [];
@@ -749,7 +778,8 @@ var Dash = GObject.registerClass({
? newApps[newIndex + 1] : null;
let insertHere = nextApp && nextApp == oldApp;
let alreadyRemoved = removedActors.reduce((result, actor) => {
- let removedApp = actor.child._delegate.app;
+ let removedApp = /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (actor.child._delegate).app;
+
return result || removedApp == newApp;
}, false);
@@ -773,9 +803,10 @@ var Dash = GObject.registerClass({
for (let i = 0; i < removedActors.length; i++) {
let item = removedActors[i];
+ // FIXME
// Don't animate item removal when the overview is transitioning
// or hidden
- if (Main.overview.visible && !Main.overview.animationInProgress)
+ if (Main.overview.visible && !Main.overview.animationInProgress && 'animateOutAndDestroy' in item)
item.animateOutAndDestroy();
else
item.destroy();
@@ -947,7 +978,7 @@ var Dash = GObject.registerClass({
children[i] == this._dragPlaceholder)
continue;
- let childId = children[i].child._delegate.app.get_id();
+ let childId = /** @type {typeof AppDisplay.AppIcon["prototype"]} */ (children[i].child._delegate).app.get_id();
if (childId == id)
continue;
if (childId in favorites)
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index d202e8436..488c1ee9d 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -1,17 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported DateMenuButton */
-const { Clutter, Gio, GLib, GnomeDesktop,
- GObject, GWeather, Pango, Shell, St } = imports.gi;
-
-const Util = imports.misc.util;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const Calendar = imports.ui.calendar;
-const Weather = imports.misc.weather;
-const System = imports.system;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GnomeDesktop from 'gi://GnomeDesktop';
+import GObject from 'gi://GObject';
+import GWeather from 'gi://GWeather';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Util from '../misc/util.js';
+import Main from './main.js';
+import * as PanelMenu from './panelMenu.js';
+import * as Calendar from './calendar.js';
+import * as Weather from '../misc/weather.js';
+import System from 'system';
+
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const NC_ = (context, str) => '%s\u0004%s'.format(context, str);
const T_ = Shell.util_translate_time_string;
@@ -24,7 +31,7 @@ const ClocksProxy = Gio.DBusProxy.makeProxyWrapper(ClocksIntegrationIface);
function _isToday(date) {
let now = new Date();
- return now.getYear() == date.getYear() &&
+ return now.getFullYear() == date.getFullYear() &&
now.getMonth() == date.getMonth() &&
now.getDate() == date.getDate();
}
@@ -33,8 +40,11 @@ function _gDateTimeToDate(datetime) {
return new Date(datetime.to_unix() * 1000 + datetime.get_microsecond() / 1000);
}
-var TodayButton = GObject.registerClass(
+export const TodayButton = GObject.registerClass(
class TodayButton extends St.Button {
+ /**
+ * @param {*} calendar
+ */
_init(calendar) {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
@@ -88,7 +98,7 @@ class TodayButton extends St.Button {
}
});
-var EventsSection = GObject.registerClass(
+export const EventsSection = GObject.registerClass(
class EventsSection extends St.Button {
_init() {
super._init({
@@ -126,7 +136,11 @@ class EventsSection extends St.Button {
this._appInstalledChanged();
}
+ /**
+ * @param {Date} date
+ */
setDate(date) {
+ /** @type {[number, number, number]} */
const day = [date.getFullYear(), date.getMonth(), date.getDate()];
this._startDate = new Date(...day);
this._endDate = new Date(...day, 23, 59, 59, 999);
@@ -158,9 +172,9 @@ class EventsSection extends St.Button {
if (this._startDate <= now && now <= this._endDate)
this._title.text = _('Today');
- else if (this._endDate < now && now - this._endDate < timeSpanDay)
+ else if (this._endDate < now && now.getTime() - this._endDate.getTime() < timeSpanDay)
this._title.text = _('Yesterday');
- else if (this._startDate > now && this._startDate - now < timeSpanDay)
+ else if (this._startDate > now && this._startDate.getTime() - now.getTime() < timeSpanDay)
this._title.text = _('Tomorrow');
else if (this._startDate.getFullYear() === now.getFullYear())
this._title.text = this._startDate.toLocaleFormat(sameYearFormat);
@@ -270,7 +284,7 @@ class EventsSection extends St.Button {
}
});
-var WorldClocksSection = GObject.registerClass(
+export const WorldClocksSection = GObject.registerClass(
class WorldClocksSection extends St.Button {
_init() {
super._init({
@@ -331,7 +345,7 @@ class WorldClocksSection extends St.Button {
this._locations = [];
let world = GWeather.Location.get_world();
- let clocks = this._settings.get_value('locations').deep_unpack();
+ let clocks = /** @type {GLib.Variant<'av'>} */ (this._settings.get_value('locations')).deep_unpack();
for (let i = 0; i < clocks.length; i++) {
let l = world.deserialize(clocks[i]);
if (l && l.get_timezone() != null)
@@ -466,7 +480,7 @@ class WorldClocksSection extends St.Button {
}
});
-var WeatherSection = GObject.registerClass(
+export const WeatherSection = GObject.registerClass(
class WeatherSection extends St.Button {
_init() {
super._init({
@@ -602,6 +616,9 @@ class WeatherSection extends St.Button {
layout.attach(label, 0, 0, 1, 1);
}
+ /**
+ * @param {GWeather.Location} loc
+ */
_findBestLocationName(loc) {
const locName = loc.get_name();
@@ -659,7 +676,7 @@ class WeatherSection extends St.Button {
}
});
-var MessagesIndicator = GObject.registerClass(
+export const MessagesIndicator = GObject.registerClass(
class MessagesIndicator extends St.Icon {
_init() {
super._init({
@@ -720,13 +737,17 @@ class MessagesIndicator extends St.Icon {
}
});
-var FreezableBinLayout = GObject.registerClass(
+export const FreezableBinLayout = GObject.registerClass(
class FreezableBinLayout extends Clutter.BinLayout {
_init() {
super._init();
this._frozen = false;
+
+ /** @type {[number, number]} */
this._savedWidth = [NaN, NaN];
+
+ /** @type {[number, number]} */
this._savedHeight = [NaN, NaN];
}
@@ -739,6 +760,9 @@ class FreezableBinLayout extends Clutter.BinLayout {
this.layout_changed();
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
if (!this._frozen || this._savedWidth.some(isNaN))
return super.vfunc_get_preferred_width(container, forHeight);
@@ -760,8 +784,11 @@ class FreezableBinLayout extends Clutter.BinLayout {
}
});
-var CalendarColumnLayout = GObject.registerClass(
+export const CalendarColumnLayout = GObject.registerClass(
class CalendarColumnLayout extends Clutter.BoxLayout {
+ /**
+ * @param {*} actors
+ */
_init(actors) {
super._init({ orientation: Clutter.Orientation.VERTICAL });
this._colActors = actors;
@@ -779,7 +806,7 @@ class CalendarColumnLayout extends Clutter.BoxLayout {
}
});
-var DateMenuButton = GObject.registerClass(
+export const DateMenuButton = GObject.registerClass(
class DateMenuButton extends PanelMenu.Button {
_init() {
let hbox;
diff --git a/js/ui/dialog.js b/js/ui/dialog.js
index 9513a8151..0a8e448ea 100644
--- a/js/ui/dialog.js
+++ b/js/ui/dialog.js
@@ -1,7 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent, ListSection, ListSectionItem */
-const { Clutter, GLib, GObject, Meta, Pango, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import St from 'gi://St';
+
function _setLabel(label, value) {
label.set({
@@ -10,8 +16,12 @@ function _setLabel(label, value) {
});
}
-var Dialog = GObject.registerClass(
+export const Dialog = GObject.registerClass(
class Dialog extends St.Widget {
+ /**
+ * @param {*} parentActor
+ * @param {*} styleClass
+ */
_init(parentActor, styleClass) {
super._init({ layout_manager: new Clutter.BinLayout() });
this.connect('destroy', this._onDestroy.bind(this));
@@ -157,7 +167,7 @@ class Dialog extends St.Widget {
}
});
-var MessageDialogContent = GObject.registerClass({
+export const MessageDialogContent = GObject.registerClass({
Properties: {
'title': GObject.ParamSpec.string(
'title', 'title', 'title',
@@ -171,6 +181,9 @@ var MessageDialogContent = GObject.registerClass({
null),
},
}, class MessageDialogContent extends St.BoxLayout {
+ /**
+ * @param {*} params
+ */
_init(params) {
this._title = new St.Label({ style_class: 'message-dialog-title' });
this._description = new St.Label({ style_class: 'message-dialog-description' });
@@ -247,7 +260,7 @@ var MessageDialogContent = GObject.registerClass({
}
});
-var ListSection = GObject.registerClass({
+export const ListSection = GObject.registerClass({
Properties: {
'title': GObject.ParamSpec.string(
'title', 'title', 'title',
@@ -256,6 +269,9 @@ var ListSection = GObject.registerClass({
null),
},
}, class ListSection extends St.BoxLayout {
+ /**
+ * @param {*} params
+ */
_init(params) {
this._title = new St.Label({ style_class: 'dialog-list-title' });
@@ -292,7 +308,7 @@ var ListSection = GObject.registerClass({
}
});
-var ListSectionItem = GObject.registerClass({
+export const ListSectionItem = GObject.registerClass({
Properties: {
'icon-actor': GObject.ParamSpec.object(
'icon-actor', 'icon-actor', 'Icon actor',
@@ -310,6 +326,9 @@ var ListSectionItem = GObject.registerClass({
null),
},
}, class ListSectionItem extends St.BoxLayout {
+ /**
+ * @param {*} params
+ */
_init(params) {
this._iconActorBin = new St.Bin();
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index a659c4fd2..3da06629b 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -1,43 +1,87 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addDragMonitor, removeDragMonitor, makeDraggable */
-const { Clutter, GLib, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Main = imports.ui.main;
+import * as Signals from '../misc/signals.js';
+
+import Main from './main.js';
// Time to scale down to maxDragActorSize
-var SCALE_ANIMATION_TIME = 250;
+export let SCALE_ANIMATION_TIME = 250;
// Time to animate to original position on cancel
-var SNAP_BACK_ANIMATION_TIME = 250;
+export let SNAP_BACK_ANIMATION_TIME = 250;
// Time to animate to original position on success
-var REVERT_ANIMATION_TIME = 750;
+export let REVERT_ANIMATION_TIME = 750;
+
+/** @typedef {{ getDragActor<T extends Clutter.Actor = Clutter.Actor>(): T }} DragActorContainer */
+/** @typedef {{ getDragActorSource<T extends Clutter.Actor = Clutter.Actor>(): T }} DragActorSourceContainer */
+/** @typedef {{ handleDragOver(source: Clutter.Actor | Signals.EventEmitter, actor: Clutter.Actor, x: number, y: number, time: number): DragMotionResult }} DragOverTarget */
+/** @typedef {{ acceptDrop(source: Clutter.Actor | Signals.EventEmitter, actor: Clutter.Actor, x: number, y: number, time: number): boolean }} DropTarget */
+
+/**
+ * @param {unknown} delegate
+ * @returns {delegate is DragActorContainer}
+ */
+function hasDragActor(delegate) {
+ return !!(/** @type {DragActorContainer} */ (delegate).getDragActor);
+}
+
+/**
+ * @param {unknown} delegate
+ * @returns {delegate is DragActorSourceContainer}
+ */
+function hasDragActorSource(delegate) {
+ return !!(/** @type {DragActorSourceContainer} */ (delegate).getDragActorSource);
+}
+
+/**
+ * @param {unknown} delegate
+ * @returns {delegate is DragOverTarget}
+ */
+export function handlesDragOver(delegate) {
+ return !!(/** @type {DragOverTarget} */ (delegate).handleDragOver);
+}
-var DragMotionResult = {
+/**
+ * @param {unknown} delegate
+ * @returns {delegate is DropTarget}
+ */
+function isDropTarget(delegate) {
+ return !!(/** @type {DropTarget} */ (delegate).acceptDrop);
+}
+
+/** @enum {number} */
+export const DragMotionResult = {
NO_DROP: 0,
COPY_DROP: 1,
MOVE_DROP: 2,
CONTINUE: 3,
};
-var DragState = {
+/** @enum {number} */
+export const DragState = {
INIT: 0,
DRAGGING: 1,
CANCELLED: 2,
};
-var DRAG_CURSOR_MAP = {
+export const DRAG_CURSOR_MAP = {
0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
1: Meta.Cursor.DND_COPY,
2: Meta.Cursor.DND_MOVE,
};
-var DragDropResult = {
+export const DragDropResult = {
FAILURE: 0,
SUCCESS: 1,
CONTINUE: 2,
};
-var dragMonitors = [];
+export let dragMonitors = [];
let eventHandlerActor = null;
let currentDraggable = null;
@@ -64,11 +108,11 @@ function _getRealActorScale(actor) {
return scale;
}
-function addDragMonitor(monitor) {
+export function addDragMonitor(monitor) {
dragMonitors.push(monitor);
}
-function removeDragMonitor(monitor) {
+export function removeDragMonitor(monitor) {
for (let i = 0; i < dragMonitors.length; i++) {
if (dragMonitors[i] == monitor) {
dragMonitors.splice(i, 1);
@@ -77,7 +121,20 @@ function removeDragMonitor(monitor) {
}
}
-var _Draggable = class _Draggable extends Signals.EventEmitter {
+// FIXME
+/**
+ * @typedef {object} _DraggableParams
+ * @property {boolean} [manualMode]
+ * @property {number} [timeoutThreshold]
+ * @property {boolean} [restoreOnSuccess]
+ * @property {number} [dragActorMaxSize]
+ * @property {number} [dragActorOpacity]
+ */
+export class _Draggable extends Signals.EventEmitter {
+ /**
+ * @param {Clutter.Actor} actor
+ * @param {Partial<_DraggableParams>} [params]
+ */
constructor(actor, params = {}) {
super();
@@ -358,7 +415,7 @@ var _Draggable = class _Draggable extends Signals.EventEmitter {
let scaledWidth, scaledHeight;
- if (this.actor._delegate && this.actor._delegate.getDragActor) {
+ if (this.actor._delegate && hasDragActor(this.actor._delegate)) {
this._dragActor = this.actor._delegate.getDragActor();
Main.uiGroup.add_child(this._dragActor);
Main.uiGroup.set_child_above_sibling(this._dragActor, null);
@@ -367,7 +424,7 @@ var _Draggable = class _Draggable extends Signals.EventEmitter {
// Drag actor does not always have to be the same as actor. For example drag actor
// can be an image that's part of the actor. So to perform "snap back" correctly we need
// to know what was the drag actor source.
- if (this.actor._delegate.getDragActorSource) {
+ if (hasDragActorSource(this.actor._delegate)) {
this._dragActorSource = this.actor._delegate.getDragActorSource();
// If the user dragged from the source, then position
// the dragActor over it. Otherwise, center it
@@ -570,7 +627,7 @@ var _Draggable = class _Draggable extends Signals.EventEmitter {
dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
while (target) {
- if (target._delegate && target._delegate.handleDragOver) {
+ if (target._delegate && handlesDragOver(target._delegate)) {
let [r_, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
@@ -643,7 +700,7 @@ var _Draggable = class _Draggable extends Signals.EventEmitter {
this._dragCancellable = false;
while (target) {
- if (target._delegate && target._delegate.acceptDrop) {
+ if (target._delegate && isDropTarget(target._delegate)) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
let accepted = false;
try {
@@ -842,6 +899,6 @@ var _Draggable = class _Draggable extends Signals.EventEmitter {
* target wants to reuse the actor, it's up to the drop target to
* reset these values.
*/
-function makeDraggable(actor, params) {
+export function makeDraggable(actor, params) {
return new _Draggable(actor, params);
}
diff --git a/js/ui/edgeDragAction.js b/js/ui/edgeDragAction.js
index 986b658e0..148dda232 100644
--- a/js/ui/edgeDragAction.js
+++ b/js/ui/edgeDragAction.js
@@ -1,19 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported EdgeDragAction */
-const { Clutter, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const Main = imports.ui.main;
+import Main from './main.js';
-var EDGE_THRESHOLD = 20;
-var DRAG_DISTANCE = 80;
+export const EDGE_THRESHOLD = 20;
+export const DRAG_DISTANCE = 80;
-var EdgeDragAction = GObject.registerClass({
+export const EdgeDragAction = GObject.registerClass({
Signals: {
'activated': {},
'progress': { param_types: [GObject.TYPE_DOUBLE] },
},
}, class EdgeDragAction extends Clutter.GestureAction {
+ /**
+ * @param {*} side
+ * @param {*} allowedModes
+ */
_init(side, allowedModes) {
super._init();
this._side = side;
diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js
index c2a314206..34a19d52e 100644
--- a/js/ui/endSessionDialog.js
+++ b/js/ui/endSessionDialog.js
@@ -17,17 +17,26 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-const { AccountsService, Clutter, Gio,
- GLib, GObject, Pango, Polkit, Shell, St, UPowerGlib: UPower } = imports.gi;
-
-const CheckBox = imports.ui.checkBox;
-const Dialog = imports.ui.dialog;
-const GnomeSession = imports.misc.gnomeSession;
-const LoginManager = imports.misc.loginManager;
-const ModalDialog = imports.ui.modalDialog;
-const UserWidget = imports.ui.userWidget;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+import AccountsService from 'gi://AccountsService';
+import Pango from 'gi://Pango';
+import Polkit from 'gi://Polkit';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import UPower from 'gi://UPowerGlib';
+
+import * as CheckBox from './checkBox.js';
+import * as Dialog from './dialog.js';
+import * as GnomeSession from '../misc/gnomeSession.js';
+import * as LoginManager from '../misc/loginManager.js';
+import * as ModalDialog from './modalDialog.js';
+import * as UserWidget from './userWidget.js';
+
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const _ITEM_ICON_SIZE = 64;
@@ -151,7 +160,7 @@ const DialogContent = {
4 /* DialogType.UPGRADE_RESTART */: restartUpgradeDialogContent,
};
-var MAX_USERS_IN_SESSION_DIALOG = 5;
+export let MAX_USERS_IN_SESSION_DIALOG = 5;
const LogindSessionIface = loadInterfaceXML('org.freedesktop.login1.Session');
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
@@ -216,14 +225,22 @@ function _setCheckBoxLabel(checkBox, text) {
}
}
-function init() {
+export function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
new EndSessionDialog();
}
-var EndSessionDialog = GObject.registerClass(
+/** @typedef {{ name?: string; version?: string; }} PreparedUpgradeInfo */
+/** @typedef {{
+ UpdateTriggered: boolean,
+ UpdatePrepared: boolean,
+ UpgradeTriggered: boolean,
+ PreparedUpgrade: PreparedUpgradeInfo }
+} UpdateInfo */
+
+export const EndSessionDialog = GObject.registerClass(
class EndSessionDialog extends ModalDialog.ModalDialog {
_init() {
super._init({ styleClass: 'end-session-dialog',
@@ -650,7 +667,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let n = 0;
for (let i = 0; i < result.length; i++) {
let [id_, uid_, userName, seat_, sessionPath] = result[i];
- let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
+ let proxy = LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
continue;
@@ -662,7 +679,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
if (!sessionId) {
this._loginManager.getCurrentSessionProxy(currentSessionProxy => {
sessionId = currentSessionProxy.Id;
- log('endSessionDialog: No XDG_SESSION_ID, fetched from logind: %d'.format(sessionId));
+ log('endSessionDialog: No XDG_SESSION_ID, fetched from logind: %s'.format(sessionId));
});
}
@@ -706,6 +723,9 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
});
}
+ /**
+ * @returns {Promise<UpdateInfo>}
+ */
async _getUpdateInfo() {
const connection = this._pkOfflineProxy.get_connection();
const reply = await connection.call(
@@ -714,12 +734,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
'org.freedesktop.DBus.Properties',
'GetAll',
new GLib.Variant('(s)', [this._pkOfflineProxy.g_interface_name]),
- null,
+ new GLib.VariantType('(a{sv})'),
Gio.DBusCallFlags.NONE,
-1,
null);
+
const [info] = reply.recursiveUnpack();
- return info;
+
+ return /** @type {UpdateInfo} */ (info);
}
async OpenAsync(parameters, invocation) {
@@ -764,7 +786,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let dialogContent = DialogContent[this._type];
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
- let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => {
+ let inhibitor = GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => {
this._onInhibitorLoaded(proxy);
});
diff --git a/js/ui/environment.js b/js/ui/environment.js
index ccd7dcdaa..16b389442 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -3,27 +3,34 @@
const Config = imports.misc.config;
-imports.gi.versions.Clutter = Config.LIBMUTTER_API_VERSION;
-imports.gi.versions.Gio = '2.0';
-imports.gi.versions.GdkPixbuf = '2.0';
-imports.gi.versions.Gtk = '3.0';
-imports.gi.versions.Soup = '3.0';
-imports.gi.versions.TelepathyGLib = '0.12';
-imports.gi.versions.TelepathyLogger = '0.2';
+import gi from "gi";
+import "gi://Gio?version=2.0";
+import "gi://GdkPixbuf?version=2.0";
+import "gi://Gtk?version=3.0";
+import "gi://TelepathyGLib?version=0.12";
+import "gi://TelepathyLogger?version=0.2";
+
+import Gio from "gi://Gio";
+import GLib from "gi://GLib";
+import GObject from "gi://GObject";
+import Meta from "gi://Meta";
+import Polkit from "gi://Polkit";
+import Shell from "gi://Shell";
+import St from "gi://St";
+import * as Gettext from "gettext";
+import System from "system";
+// import * as ExtensionUtils from '../misc/extensionUtils.js';
try {
- if (Config.HAVE_SOUP2)
- throw new Error('Soup3 support not enabled');
- const Soup_ = imports.gi.Soup;
+ if (Config.HAVE_SOUP2)
+ throw new Error('Soup3 support not enabled');
+ const Soup_ = gi.require('Soup', '3.0');
} catch (e) {
- imports.gi.versions.Soup = '2.4';
- const { Soup } = imports.gi;
- _injectSoup3Compat(Soup);
+ const Soup = gi.require('Soup', '2.4');
+ _injectSoup3Compat(Soup);
}
-const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
-const Gettext = imports.gettext;
-const System = imports.system;
+const Clutter = gi.require("Clutter", Config.LIBMUTTER_API_VERSION);
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
Gio._promisify(Gio.DataInputStream.prototype,
@@ -42,41 +49,37 @@ let _localTimeZone = null;
// variable initializations, etc, that depend on init() already having
// been run.
-
// "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
- containerClass.prototype.child_set = function (actor, props) {
- let meta = this.get_child_meta(actor);
- for (let prop in props)
- 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.
- containerClass.prototype.add = function (actor, props) {
- this.add_actor(actor);
- if (props)
- this.child_set(actor, props);
- };
+ // This one is a straightforward mapping of the C method
+ containerClass.prototype.child_set = function (actor, props) {
+ let meta = this.get_child_meta(actor);
+ for (let prop in props) 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.
+ containerClass.prototype.add = function (actor, props) {
+ this.add_actor(actor);
+ if (props) this.child_set(actor, props);
+ };
}
function _patchLayoutClass(layoutClass, styleProps) {
- if (styleProps) {
- layoutClass.prototype.hookup_style = function (container) {
- container.connect('style-changed', () => {
- let node = container.get_theme_node();
- for (let prop in styleProps) {
- let [found, length] = node.lookup_length(styleProps[prop], false);
- if (found)
- this[prop] = length;
- }
- });
- };
- }
+ if (styleProps) {
+ layoutClass.prototype.hookup_style = function (container) {
+ container.connect("style-changed", () => {
+ let node = container.get_theme_node();
+ for (let prop in styleProps) {
+ let [found, length] = node.lookup_length(styleProps[prop], false);
+ if (found) this[prop] = length;
+ }
+ });
+ };
+ }
}
/**
@@ -116,331 +119,350 @@ function _injectSoup3Compat(Soup) {
}
function _makeEaseCallback(params, cleanup) {
- let onComplete = params.onComplete;
- delete params.onComplete;
+ let onComplete = params.onComplete;
+ delete params.onComplete;
- let onStopped = params.onStopped;
- delete params.onStopped;
+ let onStopped = params.onStopped;
+ delete params.onStopped;
- return isFinished => {
- cleanup();
+ return (isFinished) => {
+ cleanup();
- if (onStopped)
- onStopped(isFinished);
- if (onComplete && isFinished)
- onComplete();
- };
+ if (onStopped) onStopped(isFinished);
+ if (onComplete && isFinished) onComplete();
+ };
}
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];
- case '@content':
- return [actor.content, name];
- case '@effects':
- return [actor.get_effect(name), prop];
- }
-
- throw new Error(`Invalid property name ${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];
+ case "@content":
+ return [actor.content, name];
+ case "@effects":
+ return [actor.get_effect(name), prop];
+ }
+
+ throw new Error(`Invalid property name ${propName}`);
}
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;
-
- 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;
-
- // 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;
-
- if (params.mode != undefined)
- actor.set_easing_mode(params.mode);
- delete params.mode;
-
- const prepare = () => {
- Meta.disable_unredirect_for_display(global.display);
- global.begin_work();
- };
- const cleanup = () => {
- Meta.enable_unredirect_for_display(global.display);
- global.end_work();
- };
- let callback = _makeEaseCallback(params, cleanup);
-
- // cancel overwritten transitions
- let animatedProps = Object.keys(params).map(p => p.replace('_', '-', 'g'));
- animatedProps.forEach(p => actor.remove_transition(p));
-
- if (actor.get_easing_duration() > 0 || !isReversed)
- actor.set(params);
- actor.restore_easing_state();
-
- let transition = animatedProps.map(p => actor.get_transition(p))
- .find(t => t !== null);
-
- if (transition && transition.delay)
- transition.connect('started', () => prepare());
- else
- prepare();
-
- if (transition) {
- transition.set({ repeatCount, autoReverse });
- transition.connect('stopped', (t, finished) => callback(finished));
- } else {
- callback(true);
- }
+ 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;
+
+ 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;
+
+ // 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;
+
+ if (params.mode != undefined) actor.set_easing_mode(params.mode);
+ delete params.mode;
+
+ const prepare = () => {
+ Meta.disable_unredirect_for_display(global.display);
+ global.begin_work();
+ };
+ const cleanup = () => {
+ Meta.enable_unredirect_for_display(global.display);
+ global.end_work();
+ };
+ let callback = _makeEaseCallback(params, cleanup);
+
+ // cancel overwritten transitions
+ let animatedProps = Object.keys(params).map((p) => p.replace(/_/g, "-"));
+ animatedProps.forEach((p) => actor.remove_transition(p));
+
+ if (actor.get_easing_duration() > 0 || !isReversed) actor.set(params);
+ actor.restore_easing_state();
+
+ let transition = animatedProps.map((p) => actor.get_transition(p)).find((t) => t !== null);
+
+ if (transition && transition.delay) transition.connect("started", () => prepare());
+ else prepare();
+
+ if (transition) {
+ transition.set({ repeatCount, autoReverse });
+ transition.connect("stopped", (t, finished) => callback(finished));
+ } else {
+ callback(true);
+ }
}
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);
-
- 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;
-
- // 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;
-
- // Copy Clutter's behavior for implicit animations, see
- // should_skip_implicit_transition()
- if (actor instanceof Clutter.Actor && !actor.mapped)
- duration = 0;
-
- const prepare = () => {
- Meta.disable_unredirect_for_display(global.display);
- global.begin_work();
- };
- const cleanup = () => {
- Meta.enable_unredirect_for_display(global.display);
- global.end_work();
- };
- let callback = _makeEaseCallback(params, cleanup);
-
- // cancel overwritten transition
- actor.remove_transition(propName);
-
- if (duration == 0) {
- let [obj, prop] = _getPropertyTarget(actor, propName);
-
- if (!isReversed)
- obj[prop] = target;
-
- prepare();
- callback(true);
-
- return;
- }
-
- let pspec = actor.find_property(propName);
- let transition = new Clutter.PropertyTransition(Object.assign({
+ // 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);
+
+ 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;
+
+ // 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;
+
+ // Copy Clutter's behavior for implicit animations, see
+ // should_skip_implicit_transition()
+ if (actor instanceof Clutter.Actor && !actor.mapped) duration = 0;
+
+ const prepare = () => {
+ Meta.disable_unredirect_for_display(global.display);
+ global.begin_work();
+ };
+ const cleanup = () => {
+ Meta.enable_unredirect_for_display(global.display);
+ global.end_work();
+ };
+ let callback = _makeEaseCallback(params, cleanup);
+
+ // cancel overwritten transition
+ actor.remove_transition(propName);
+
+ if (duration == 0) {
+ let [obj, prop] = _getPropertyTarget(actor, propName);
+
+ if (!isReversed) obj[prop] = target;
+
+ prepare();
+ callback(true);
+
+ 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 }),
remove_on_complete: true,
repeat_count: repeatCount,
auto_reverse: autoReverse,
- }, params));
- actor.add_transition(propName, transition);
+ },
+ params
+ )
+ );
+ actor.add_transition(propName, transition);
- transition.set_to(target);
+ transition.set_to(target);
- if (transition.delay)
- transition.connect('started', () => prepare());
- else
- prepare();
+ if (transition.delay) transition.connect("started", () => prepare());
+ else prepare();
- transition.connect('stopped', (t, finished) => callback(finished));
+ transition.connect("stopped", (t, finished) => callback(finished));
}
function _loggingFunc(...args) {
- let fields = { 'MESSAGE': args.join(', ') };
- 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);
+ let fields = { MESSAGE: args.join(", ") };
+ let domain = "GNOME Shell";
+
+ // If the caller is an extension, add it as metadata
+ // let extension = 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);
}
-function init() {
- // Add some bindings to the global JS namespace
- globalThis.global = Shell.Global.get();
-
- globalThis.log = _loggingFunc;
-
- globalThis._ = Gettext.gettext;
- globalThis.C_ = Gettext.pgettext;
- globalThis.ngettext = Gettext.ngettext;
- globalThis.N_ = s => s;
-
- GObject.gtypeNameBasedOnJSPath = true;
-
- // Miscellaneous monkeypatching
- _patchContainerClass(St.BoxLayout);
-
- _patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
- column_spacing: 'spacing-columns' });
- _patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
-
- let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
- Clutter.Actor.prototype.set_easing_duration = function (msecs) {
- origSetEasingDuration.call(this, adjustAnimationTime(msecs));
- };
- let origSetEasingDelay = Clutter.Actor.prototype.set_easing_delay;
- Clutter.Actor.prototype.set_easing_delay = function (msecs) {
- origSetEasingDelay.call(this, adjustAnimationTime(msecs));
- };
-
- Clutter.Actor.prototype.ease = function (props) {
- _easeActor(this, props);
- };
- Clutter.Actor.prototype.ease_property = function (propName, target, params) {
- _easeActorProperty(this, propName, target, params);
- };
- St.Adjustment.prototype.ease = function (target, params) {
- // 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);
- };
-
- Clutter.Actor.prototype[Symbol.iterator] = function* () {
- for (let c = this.get_first_child(); c; c = c.get_next_sibling())
- yield c;
- };
-
- Clutter.Actor.prototype.toString = function () {
- return St.describe_actor(this);
- };
- // 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;
- },
- });
-
- 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);
- };
-
- St.set_slow_down_factor = function (factor) {
- 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;
- };
+log("initializing...");
+// Add some bindings to the global JS namespace
+
+// TODO: This errors because the Shell global has an incorrect type for 'stage'
+/** @type {Shell.Global & { stage: import('gi://Clutter').Stage; }} */
+globalThis.global = (Shell.Global.get());
+
+globalThis.log = _loggingFunc;
+
+globalThis._ = Gettext.gettext;
+globalThis.C_ = Gettext.pgettext;
+globalThis.ngettext = Gettext.ngettext;
+globalThis.N_ = (s) => s;
+
+globalThis.assertType =
+ /**
+ * @template T
+ * @param {unknown} obj
+ * @param {new(...args: any[]) => T} type
+ * @param {string} [message]
+ * @returns {asserts obj is T}
+ */
+ (obj, type, message) => {
+ if (!(obj instanceof type)) {
+ throw new Error(`${obj} is not an instance of ${type.name}${message ? `: ${message}` : ""}`);
+ }
+ };
+
+GObject.gtypeNameBasedOnJSPath = true;
+
+// Miscellaneous monkeypatching
+_patchContainerClass(St.BoxLayout);
+
+_patchLayoutClass(Clutter.GridLayout, { row_spacing: "spacing-rows", column_spacing: "spacing-columns" });
+_patchLayoutClass(Clutter.BoxLayout, { spacing: "spacing" });
+
+let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
+Clutter.Actor.prototype.set_easing_duration = function (msecs) {
+ origSetEasingDuration.call(this, adjustAnimationTime(msecs));
+};
+let origSetEasingDelay = Clutter.Actor.prototype.set_easing_delay;
+Clutter.Actor.prototype.set_easing_delay = function (msecs) {
+ origSetEasingDelay.call(this, adjustAnimationTime(msecs));
+};
+
+Clutter.Actor.prototype.ease = function (props) {
+ _easeActor(this, props);
+};
+Clutter.Actor.prototype.ease_property = function (propName, target, params) {
+ _easeActorProperty(this, propName, target, params);
+};
+St.Adjustment.prototype.ease = function (target, params) {
+ // 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);
+};
+
+Clutter.Actor.prototype[Symbol.iterator] = function* () {
+ for (let c = this.get_first_child(); c; c = c.get_next_sibling()) yield c;
+};
+
+Clutter.Actor.prototype.toString = function () {
+ return St.describe_actor(this);
+};
+// 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;
+ },
+});
+
+Gio._LocalFilePrototype.touch_async = function (callback) {
+ // TODO
+ if (!callback) {
+ return Shell.util_touch_file_async(this);
+ }
+
+ Shell.util_touch_file_async(this, callback);
+};
+
+Gio._LocalFilePrototype.touch_finish =
+ /**
+ * @this {Gio.File}
+ * @param {Gio.AsyncResult} result
+ */
+ function (result) {
+ return Shell.util_touch_file_finish(this, result);
+ };
+
+St.set_slow_down_factor = function (factor) {
+ 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;
+};
- let origToString = Object.prototype.toString;
- Object.prototype.toString = function () {
- let base = origToString.call(this);
- try {
- if ('actor' in this && this.actor instanceof Clutter.Actor)
- return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
- else
- return base;
- } catch (e) {
- return base;
- }
- };
+/**
+ * @param {unknown} obj
+ * @returns {obj is {actor: unknown}}
+ */
+function hasActor(obj) {
+ let actorObj = /** @type {{actor?: unknown}} */ (obj);
- // Override to clear our own timezone cache as well
- const origClearDateCaches = System.clearDateCaches;
- System.clearDateCaches = function () {
- _localTimeZone = null;
- origClearDateCaches();
- };
+ return "actor" in actorObj;
+}
- // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
- Date.prototype.toLocaleFormat = function (format) {
- if (_localTimeZone === null)
- _localTimeZone = GLib.TimeZone.new_local();
-
- let dt = GLib.DateTime.new(_localTimeZone,
- this.getFullYear(),
- this.getMonth() + 1,
- this.getDate(),
- this.getHours(),
- this.getMinutes(),
- this.getSeconds());
- return dt?.format(format) ?? '';
- };
+let origToString = Object.prototype.toString;
+Object.prototype.toString = function () {
+ let base = origToString.call(this);
+ try {
+ if (hasActor(this) && this.actor instanceof Clutter.Actor)
+ return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
+ else return base;
+ } catch (e) {
+ return base;
+ }
+};
+
+// Override to clear our own timezone cache as well
+const origClearDateCaches = System.clearDateCaches;
+System.clearDateCaches = function () {
+ _localTimeZone = null;
+ origClearDateCaches();
+};
+
+// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
+Date.prototype.toLocaleFormat = function (format) {
+ if (_localTimeZone === null) _localTimeZone = GLib.TimeZone.new_local();
+
+ let dt = GLib.DateTime.new(
+ _localTimeZone,
+ this.getFullYear(),
+ this.getMonth() + 1,
+ this.getDate(),
+ this.getHours(),
+ this.getMinutes(),
+ this.getSeconds()
+ );
+ return dt?.format(format) ?? "";
+};
+
+let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
+if (slowdownEnv) {
+ let factor = parseFloat(slowdownEnv);
+ if (!isNaN(factor) && factor > 0.0) St.Settings.get().slow_down_factor = factor;
+}
- let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
- if (slowdownEnv) {
- let factor = parseFloat(slowdownEnv);
- if (!isNaN(factor) && factor > 0.0)
- St.Settings.get().slow_down_factor = factor;
- }
+// OK, now things are initialized enough that we can import shell JS
+const Format = imports.format;
- // OK, now things are initialized enough that we can import shell JS
- const Format = imports.format;
+String.prototype.format = Format.format;
- String.prototype.format = Format.format;
+Math.clamp = function (x, lower, upper) {
+ return Math.min(Math.max(x, lower), upper);
+};
- Math.clamp = function (x, lower, upper) {
- return Math.min(Math.max(x, lower), upper);
- };
-}
+log("done initializing...");
// 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();
+export function adjustAnimationTime(msecs) {
+ let settings = St.Settings.get();
- if (!settings.enable_animations)
- return 1;
- return settings.slow_down_factor * msecs;
+ if (!settings.enable_animations) return 1;
+ return settings.slow_down_factor * msecs;
}
-
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
index 8bf4646a6..8a6e51633 100644
--- a/js/ui/extensionDownloader.js
+++ b/js/ui/extensionDownloader.js
@@ -1,14 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, installExtension, uninstallExtension, checkForUpdates */
-const { Clutter, Gio, GLib, GObject, Soup } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Soup from 'gi://Soup';
const Config = imports.misc.config;
-const Dialog = imports.ui.dialog;
-const ExtensionUtils = imports.misc.extensionUtils;
-const FileUtils = imports.misc.fileUtils;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
+import * as Dialog from './dialog.js';
+import * as ExtensionUtils from '../misc/extensionUtils.js';
+import * as FileUtils from '../misc/fileUtilsModule.js';
+import Main from './main.js';
+import * as ModalDialog from './modalDialog.js';
Gio._promisify(Soup.Session.prototype,
'send_and_read_async', 'send_and_read_finish');
@@ -19,10 +23,10 @@ Gio._promisify(Gio.IOStream.prototype,
Gio._promisify(Gio.Subprocess.prototype,
'wait_check_async', 'wait_check_finish');
-var REPOSITORY_URL_DOWNLOAD = 'https://extensions.gnome.org/download-extension/%s.shell-extension.zip';
-var REPOSITORY_URL_INFO = 'https://extensions.gnome.org/extension-info/';
-var REPOSITORY_URL_UPDATE = 'https://extensions.gnome.org/update-info/';
-
+export const REPOSITORY_URL_DOWNLOAD = 'https://extensions.gnome.org/download-extension/%s.shell-extension.zip';
+export const REPOSITORY_URL_INFO = 'https://extensions.gnome.org/extension-info/';
+export const REPOSITORY_URL_UPDATE = 'https://extensions.gnome.org/update-info/';
+
let _httpSession;
/**
@@ -60,7 +64,7 @@ async function installExtension(uuid, invocation) {
dialog.open(global.get_current_time());
}
-function uninstallExtension(uuid) {
+export function uninstallExtension(uuid) {
let extension = Main.extensionManager.lookup(uuid);
if (!extension)
return false;
@@ -215,7 +219,7 @@ async function checkForUpdates() {
}
}
-var InstallExtensionDialog = GObject.registerClass(
+export const InstallExtensionDialog = GObject.registerClass(
class InstallExtensionDialog extends ModalDialog.ModalDialog {
_init(uuid, info, invocation) {
super._init({ styleClass: 'extension-dialog' });
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 3c1508d77..21baa4ab5 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -1,14 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect ExtensionManager */
-const { GLib, Gio, GObject, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const ExtensionDownloader = imports.ui.extensionDownloader;
-const ExtensionUtils = imports.misc.extensionUtils;
-const FileUtils = imports.misc.fileUtils;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
+import GLib from 'gi://GLib';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
+
+import * as ExtensionDownloader from './extensionDownloader.js';
+import * as ExtensionUtils from '../misc/extensionUtils.js';
+import * as FileUtils from '../misc/fileUtilsModule.js';
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
const { ExtensionState, ExtensionType } = ExtensionUtils;
@@ -19,7 +23,7 @@ const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validatio
const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds
-var ExtensionManager = class extends Signals.EventEmitter {
+export class ExtensionManager extends Signals.EventEmitter {
constructor() {
super();
@@ -418,35 +422,36 @@ var ExtensionManager = class extends Signals.EventEmitter {
let extensionModule;
let extensionState = null;
- ExtensionUtils.installImporter(extension);
+ // TODO: Fix extension initialization.
+ // ExtensionUtils.installImporter(extension);
try {
- extensionModule = extension.imports.extension;
+ // extensionModule = extension.imports.extension;
} catch (e) {
this.logExtensionError(uuid, e);
return false;
}
- if (extensionModule.init) {
- try {
- extensionState = extensionModule.init(extension);
- } catch (e) {
- this.logExtensionError(uuid, e);
- return false;
- }
- }
+ // if (extensionModule.init) {
+ // try {
+ // extensionState = extensionModule.init(extension);
+ // } catch (e) {
+ // this.logExtensionError(uuid, e);
+ // return false;
+ // }
+ // }
- if (!extensionState)
- extensionState = extensionModule;
- extension.stateObj = extensionState;
+ // if (!extensionState)
+ // extensionState = extensionModule;
+ // extension.stateObj = extensionState;
- extension.state = ExtensionState.DISABLED;
- this.emit('extension-loaded', uuid);
- return true;
+ // extension.state = ExtensionState.DISABLED;
+ // this.emit('extension-loaded', uuid);
+ return false;
}
_getModeExtensions() {
- if (Array.isArray(Main.sessionMode.enabledExtensions))
- return Main.sessionMode.enabledExtensions;
+ // if (Array.isArray(Main.sessionMode.enabledExtensions))
+ // return Main.sessionMode.enabledExtensions;
return [];
}
@@ -499,7 +504,7 @@ var ExtensionManager = class extends Signals.EventEmitter {
.filter(uuid => !newEnabledExtensions.includes(uuid))
.reverse().forEach(uuid => this._callExtensionDisable(uuid));
- this._enabledExtensions = newEnabledExtensions;
+ this._enabledExtensions = []; //newEnabledExtensions;
}
_onSettingsWritableChanged() {
@@ -625,10 +630,10 @@ var ExtensionManager = class extends Signals.EventEmitter {
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
// Take care of added or removed sessionMode extensions
- this._onEnabledExtensionsChanged();
- this._enableAllExtensions();
+ // this._onEnabledExtensionsChanged();
+ // this._enableAllExtensions();
} else {
- this._disableAllExtensions();
+ // this._disableAllExtensions();
}
}
};
@@ -639,7 +644,7 @@ class ExtensionUpdateSource extends MessageTray.Source {
let appSys = Shell.AppSystem.get_default();
this._app = appSys.lookup_app('org.gnome.Extensions.desktop');
- super._init(this._app.get_name());
+ super._init({ title: this._app.get_name() });
}
getIcon() {
diff --git a/js/ui/focusCaretTracker.js b/js/ui/focusCaretTracker.js
index 5cfe7a849..456fa7dd0 100644
--- a/js/ui/focusCaretTracker.js
+++ b/js/ui/focusCaretTracker.js
@@ -22,13 +22,13 @@
*/
/* exported FocusCaretTracker */
-const Atspi = imports.gi.Atspi;
-const Signals = imports.misc.signals;
+import Atspi from 'gi://Atspi';
+import * as Signals from '../misc/signals.js';
const CARETMOVED = 'object:text-caret-moved';
const STATECHANGED = 'object:state-changed';
-var FocusCaretTracker = class FocusCaretTracker extends Signals.EventEmitter {
+export class FocusCaretTracker extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/ui/grabHelper.js b/js/ui/grabHelper.js
index 72c1fec44..84fdc8503 100644
--- a/js/ui/grabHelper.js
+++ b/js/ui/grabHelper.js
@@ -1,9 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GrabHelper */
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
-const Main = imports.ui.main;
+
+import Main from './main.js';
let _capturedEventId = 0;
let _grabHelperStack = [];
@@ -30,6 +32,8 @@ function _popGrabHelper(grabHelper) {
}
}
+/** @typedef {{ actor: St.Widget, focus?: St.Widget, savedFocus?: Clutter.Actor, onUngrab: (isUser: boolean) => void }} Grab */
+
// GrabHelper:
// @owner: the actor that owns the GrabHelper
// @params: optional parameters to pass to Main.pushModal()
@@ -41,7 +45,7 @@ function _popGrabHelper(grabHelper) {
// your code just needs to deal with it; you shouldn't adjust behavior directly
// after you call ungrab(), but instead pass an 'onUngrab' callback when you
// call grab().
-var GrabHelper = class GrabHelper {
+export class GrabHelper {
constructor(owner, params) {
if (!(owner instanceof Clutter.Actor))
throw new Error('GrabHelper owner must be a Clutter.Actor');
diff --git a/js/ui/ibusCandidatePopup.js b/js/ui/ibusCandidatePopup.js
index 5a9fe7792..129e2c5fd 100644
--- a/js/ui/ibusCandidatePopup.js
+++ b/js/ui/ibusCandidatePopup.js
@@ -1,17 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
-const { Clutter, GObject, IBus, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import IBus from 'gi://IBus';
+import St from 'gi://St';
-const BoxPointer = imports.ui.boxpointer;
-const Main = imports.ui.main;
-var MAX_CANDIDATES_PER_PAGE = 16;
+import * as BoxPointer from './boxpointer.js';
+import Main from './main.js';
-var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
+export let MAX_CANDIDATES_PER_PAGE = 16;
+
+export let DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
-var CandidateArea = GObject.registerClass({
+export const CandidateArea = GObject.registerClass({
Signals: {
'candidate-clicked': { param_types: [GObject.TYPE_UINT,
GObject.TYPE_UINT,
@@ -98,12 +102,20 @@ var CandidateArea = GObject.registerClass({
this.vertical = false;
this.remove_style_class_name('vertical');
this.add_style_class_name('horizontal');
+
+ assertType(this._previousButton.child, St.Icon);
+ assertType(this._nextButton.child, St.Icon);
+
this._previousButton.child.icon_name = 'go-previous-symbolic';
this._nextButton.child.icon_name = 'go-next-symbolic';
} else { // VERTICAL || SYSTEM
this.vertical = true;
this.add_style_class_name('vertical');
this.remove_style_class_name('horizontal');
+
+ assertType(this._previousButton.child, St.Icon);
+ assertType(this._nextButton.child, St.Icon);
+
this._previousButton.child.icon_name = 'go-up-symbolic';
this._nextButton.child.icon_name = 'go-down-symbolic';
}
@@ -139,7 +151,7 @@ var CandidateArea = GObject.registerClass({
}
});
-var CandidatePopup = GObject.registerClass(
+export const CandidatePopup = GObject.registerClass(
class IbusCandidatePopup extends BoxPointer.BoxPointer {
_init() {
super._init(St.Side.TOP);
@@ -199,6 +211,7 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
panelService.connect('set-cursor-location-relative', (ps, x, y, w, h) => {
if (!global.display.focus_window)
return;
+
let window = global.display.focus_window.get_compositor_private();
this._setDummyCursorGeometry(window.x + x, window.y + y, w, h);
});
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 4f011fe67..1c84163cd 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -1,37 +1,49 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, IconGridLayout */
-const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Main = imports.ui.main;
+import Main from './main.js';
-var ICON_SIZE = 96;
+export let ICON_SIZE = 96;
-var ANIMATION_TIME_IN = 350;
-var ANIMATION_TIME_OUT = 1 / 2 * ANIMATION_TIME_IN;
-var ANIMATION_MAX_DELAY_FOR_ITEM = 2 / 3 * ANIMATION_TIME_IN;
-var ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2 / 3 * ANIMATION_TIME_OUT;
-var ANIMATION_FADE_IN_TIME_FOR_ITEM = 1 / 4 * ANIMATION_TIME_IN;
+export let ANIMATION_TIME_IN = 350;
+export let ANIMATION_TIME_OUT = 1 / 2 * ANIMATION_TIME_IN;
+export let ANIMATION_MAX_DELAY_FOR_ITEM = 2 / 3 * ANIMATION_TIME_IN;
+export let ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2 / 3 * ANIMATION_TIME_OUT;
+export let ANIMATION_FADE_IN_TIME_FOR_ITEM = 1 / 4 * ANIMATION_TIME_IN;
-var PAGE_SWITCH_TIME = 300;
+export let PAGE_SWITCH_TIME = 300;
-var AnimationDirection = {
+/** @typedef {Clutter.Actor & { icon?: typeof BaseIcon["prototype"] }} BaseItem */
+
+/** @enum {number} */
+export const AnimationDirection = {
IN: 0,
OUT: 1,
};
-var IconSize = {
+/** @enum {number} */
+export const IconSize = {
LARGE: 96,
MEDIUM: 64,
SMALL: 32,
TINY: 16,
};
-var APPICON_ANIMATION_OUT_SCALE = 3;
-var APPICON_ANIMATION_OUT_TIME = 250;
+export let APPICON_ANIMATION_OUT_SCALE = 3;
+export let APPICON_ANIMATION_OUT_TIME = 250;
const ICON_POSITION_DELAY = 10;
+/** @typedef {{rows: number, columns: number}} GridMode */
+
+/** @type {GridMode[]} */
const defaultGridModes = [
{
rows: 8,
@@ -51,10 +63,11 @@ const defaultGridModes = [
},
];
-var LEFT_DIVIDER_LEEWAY = 20;
-var RIGHT_DIVIDER_LEEWAY = 20;
+export let LEFT_DIVIDER_LEEWAY = 20;
+export let RIGHT_DIVIDER_LEEWAY = 20;
-var DragLocation = {
+/** @enum {number} */
+export const DragLocation = {
INVALID: 0,
START_EDGE: 1,
ON_ICON: 2,
@@ -62,7 +75,7 @@ var DragLocation = {
EMPTY_SPACE: 4,
};
-var BaseIcon = GObject.registerClass(
+export const BaseIcon = GObject.registerClass(
class BaseIcon extends Shell.SquareBin {
_init(label, params = {}) {
const {
@@ -114,6 +127,10 @@ class BaseIcon extends Shell.SquareBin {
// This can be overridden by a subclass, or by the createIcon
// parameter to _init()
+ /**
+ * @param {number} _size
+ * @returns {St.Widget}
+ */
createIcon(_size) {
throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`);
}
@@ -186,7 +203,7 @@ class BaseIcon extends Shell.SquareBin {
}
});
-function zoomOutActor(actor) {
+export function zoomOutActor(actor) {
let [x, y] = actor.get_transformed_position();
zoomOutActorAtPos(actor, x, y);
}
@@ -250,7 +267,7 @@ function swap(value, length) {
return length - value - 1;
}
-var IconGridLayout = GObject.registerClass({
+export const IconGridLayout = GObject.registerClass({
Properties: {
'allow-incomplete-pages': GObject.ParamSpec.boolean('allow-incomplete-pages',
'Allow incomplete pages', 'Allow incomplete pages',
@@ -319,6 +336,7 @@ var IconGridLayout = GObject.registerClass({
'pages-changed': {},
},
}, class IconGridLayout extends Clutter.LayoutManager {
+
_init(params = {}) {
this._orientation = params.orientation ?? Clutter.Orientation.VERTICAL;
@@ -327,6 +345,29 @@ var IconGridLayout = GObject.registerClass({
if (!this.pagePadding)
this.pagePadding = new Clutter.Margin();
+ /** @type {number} */
+ this.fixedIconSize;
+ /** @type {number} */
+ this.rowSpacing;
+ /** @type {number} */
+ this.columnSpacing;
+ /** @type {number} */
+ this.maxRowSpacing;
+ /** @type {number} */
+ this.maxColumnSpacing;
+ /** @type {number} */
+ this.columnsPerPage;
+ /** @type {number} */
+ this.rowsPerPage;
+ /** @type {number} */
+ this.lastRowAlign;
+ /** @type {number} */
+ this.allowIncompletePages;
+ /** @type {Clutter.ActorAlign} */
+ this.pageHalign;
+ /** @type {Clutter.ActorAlign} */
+ this.pageValign;
+
this._iconSize = this.fixedIconSize !== -1
? this.fixedIconSize
: IconSize.LARGE;
@@ -729,6 +770,9 @@ var IconGridLayout = GObject.registerClass({
this._containerDestroyedId = this._container.connect('destroy', this._onDestroy.bind(this));
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(_container, _forHeight) {
let minWidth = -1;
let natWidth = -1;
@@ -748,6 +792,9 @@ var IconGridLayout = GObject.registerClass({
return [minWidth, natWidth];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(_container, _forWidth) {
let minHeight = -1;
let natHeight = -1;
@@ -840,8 +887,8 @@ var IconGridLayout = GObject.registerClass({
/**
* addItem:
* @param {Clutter.Actor} item: item to append to the grid
- * @param {int} page: page number
- * @param {int} index: position in the page
+ * @param {number} page: page number
+ * @param {number} index: position in the page
*
* Adds @item to the grid. @item must not be part of the grid.
*
@@ -880,8 +927,8 @@ var IconGridLayout = GObject.registerClass({
/**
* moveItem:
* @param {Clutter.Actor} item: item to move
- * @param {int} newPage: new page of the item
- * @param {int} newPosition: new page of the item
+ * @param {number} newPage: new page of the item
+ * @param {number} newPosition: new page of the item
*
* Moves @item to the grid. @item must be part of the grid.
*/
@@ -916,7 +963,7 @@ var IconGridLayout = GObject.registerClass({
/**
* getItemsAtPage:
- * @param {int} pageIndex: page index
+ * @param {number} pageIndex: page index
*
* Retrieves the children at page @pageIndex. Children may be invisible.
*
@@ -931,12 +978,12 @@ var IconGridLayout = GObject.registerClass({
/**
* getItemPosition:
- * @param {BaseIcon} item: the item
+ * @param {BaseIcon["prototype"]} item: the item
*
* Retrieves the position of @item is its page, or -1 if @item is not
* part of the grid.
*
- * @returns {[int, int]} the page and position of @item
+ * @returns {[number, number]} the page and position of @item
*/
getItemPosition(item) {
if (!this._items.has(item))
@@ -950,8 +997,8 @@ var IconGridLayout = GObject.registerClass({
/**
* getItemAt:
- * @param {int} page: the page
- * @param {int} position: the position in page
+ * @param {number} page: the page
+ * @param {number} position: the position in page
*
* Retrieves the item at @page and @position.
*
@@ -971,11 +1018,11 @@ var IconGridLayout = GObject.registerClass({
/**
* getItemPage:
- * @param {BaseIcon} item: the item
+ * @param {BaseIcon["prototype"]} item: the item
*
* Retrieves the page @item is in, or -1 if @item is not part of the grid.
*
- * @returns {int} the page where @item is in
+ * @returns {number} the page where @item is in
*/
getItemPage(item) {
if (!this._items.has(item))
@@ -1023,13 +1070,13 @@ var IconGridLayout = GObject.registerClass({
/**
* getDropTarget:
- * @param {int} x: position of the horizontal axis
- * @param {int} y: position of the vertical axis
+ * @param {number} x: position of the horizontal axis
+ * @param {number} y: position of the vertical axis
*
* Retrieves the item located at (@x, @y), as well as the drag location.
* Both @x and @y are relative to the grid.
*
- * @returns {[Clutter.Actor, DragLocation]} the item and drag location
+ * @returns {[BaseIcon["prototype"] | null, DragLocation]} the item and drag location
* under (@x, @y)
*/
getDropTarget(x, y) {
@@ -1154,12 +1201,17 @@ var IconGridLayout = GObject.registerClass({
}
});
-var IconGrid = GObject.registerClass({
+export const IconGrid = GObject.registerClass({
Signals: {
'pages-changed': {},
'animation-done': {},
},
-}, class IconGrid extends St.Viewport {
+},
+/** @extends {St.Viewport<typeof IconGridLayout["prototype"]>} */
+class IconGrid extends St.Viewport {
+ /**
+ * @param {*} layoutParams
+ */
_init(layoutParams = {}) {
const iconGridLayoutParams = {
allow_incomplete_pages: false,
@@ -1238,6 +1290,9 @@ var IconGrid = GObject.registerClass({
this.goToPage(itemPage);
}
+ /**
+ * @param {number} modeIndex
+ */
_setGridMode(modeIndex) {
if (this._currentMode === modeIndex)
return;
@@ -1259,17 +1314,16 @@ var IconGrid = GObject.registerClass({
const sizeRatio = width / height;
let closestRatio = Infinity;
- let bestMode = -1;
-
- for (let modeIndex in this._gridModes) {
- const mode = this._gridModes[modeIndex];
+ let bestMode = this._gridModes.findIndex((mode) => {
const modeRatio = mode.columns / mode.rows;
if (Math.abs(sizeRatio - modeRatio) < Math.abs(sizeRatio - closestRatio)) {
closestRatio = modeRatio;
- bestMode = modeIndex;
+ return true;
}
- }
+
+ return false;
+ }) ?? -1;
this._setGridMode(bestMode);
}
@@ -1312,9 +1366,9 @@ var IconGrid = GObject.registerClass({
/**
* addItem:
- * @param {Clutter.Actor} item: item to append to the grid
- * @param {int} page: page number
- * @param {int} index: position in the page
+ * @param {BaseItem} item: item to append to the grid
+ * @param {number} page: page number
+ * @param {number} index: position in the page
*
* Adds @item to the grid. @item must not be part of the grid.
*
@@ -1344,8 +1398,8 @@ var IconGrid = GObject.registerClass({
/**
* moveItem:
* @param {Clutter.Actor} item: item to move
- * @param {int} newPage: new page of the item
- * @param {int} newPosition: new page of the item
+ * @param {number} newPage: new page of the item
+ * @param {number} newPosition: new page of the item
*
* Moves @item to the grid. @item must be part of the grid.
*/
@@ -1369,7 +1423,7 @@ var IconGrid = GObject.registerClass({
/**
* goToPage:
- * @param {int} pageIndex: page index
+ * @param {number} pageIndex: page index
* @param {boolean} animate: animate the page transition
*
* Moves the current page to @pageIndex. @pageIndex must be a valid page
@@ -1405,11 +1459,11 @@ var IconGrid = GObject.registerClass({
/**
* getItemPage:
- * @param {BaseIcon} item: the item
+ * @param {BaseIcon["prototype"]} item: the item
*
* Retrieves the page @item is in, or -1 if @item is not part of the grid.
*
- * @returns {int} the page where @item is in
+ * @returns {number} the page where @item is in
*/
getItemPage(item) {
return this.layout_manager.getItemPage(item);
@@ -1417,12 +1471,12 @@ var IconGrid = GObject.registerClass({
/**
* getItemPosition:
- * @param {BaseIcon} item: the item
+ * @param {BaseIcon["prototype"]} item: the item
*
* Retrieves the position of @item is its page, or -1 if @item is not
* part of the grid.
*
- * @returns {[int, int]} the page and position of @item
+ * @returns {[number, number]} the page and position of @item
*/
getItemPosition(item) {
if (!this.contains(item))
@@ -1434,8 +1488,8 @@ var IconGrid = GObject.registerClass({
/**
* getItemAt:
- * @param {int} page: the page
- * @param {int} position: the position in page
+ * @param {number} page: the page
+ * @param {number} position: the position in page
*
* Retrieves the item at @page and @position.
*
@@ -1448,7 +1502,7 @@ var IconGrid = GObject.registerClass({
/**
* getItemsAtPage:
- * @param {int} page: the page index
+ * @param {number} page: the page index
*
* Retrieves the children at page @page, including invisible children.
*
@@ -1553,11 +1607,9 @@ var IconGrid = GObject.registerClass({
duration: ANIMATION_TIME_IN,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
+ ...(isLastItem ? { onComplete: this._animationDone.bind(this) } : {})
};
- if (isLastItem)
- movementParams.onComplete = this._animationDone.bind(this);
-
fadeParams = {
opacity: 255,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
@@ -1579,11 +1631,9 @@ var IconGrid = GObject.registerClass({
duration: ANIMATION_TIME_OUT,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
+ ...(isLastItem ? { onComplete: this._animationDone.bind(this) } : {})
};
- if (isLastItem)
- movementParams.onComplete = this._animationDone.bind(this);
-
fadeParams = {
opacity: 0,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
@@ -1597,6 +1647,9 @@ var IconGrid = GObject.registerClass({
});
}
+ /**
+ * @param {GridMode[]} modes
+ */
setGridModes(modes) {
this._gridModes = modes ? modes : defaultGridModes;
this.queue_relayout();
@@ -1604,7 +1657,7 @@ var IconGrid = GObject.registerClass({
getDropTarget(x, y) {
const layoutManager = this.layout_manager;
- return layoutManager.getDropTarget(x, y, this._currentPage);
+ return layoutManager.getDropTarget(x, y);
}
get itemsPerPage() {
diff --git a/js/ui/inhibitShortcutsDialog.js b/js/ui/inhibitShortcutsDialog.js
index b20e67285..23734da14 100644
--- a/js/ui/inhibitShortcutsDialog.js
+++ b/js/ui/inhibitShortcutsDialog.js
@@ -1,9 +1,17 @@
/* exported InhibitShortcutsDialog */
-const { Clutter, Gio, GLib, GObject, Gtk, Meta, Pango, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const ModalDialog = imports.ui.modalDialog;
-const PermissionStore = imports.misc.permissionStore;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Dialog from './dialog.js';
+import * as ModalDialog from './modalDialog.js';
+import * as PermissionStore from '../misc/permissionStore.js';
const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
@@ -13,14 +21,17 @@ const APP_PERMISSIONS_ID = 'shortcuts-inhibitor';
const GRANTED = 'GRANTED';
const DENIED = 'DENIED';
-var DialogResponse = Meta.InhibitShortcutsDialogResponse;
+export const DialogResponse = Meta.InhibitShortcutsDialogResponse;
-var InhibitShortcutsDialog = GObject.registerClass({
+export const InhibitShortcutsDialog = GObject.registerClass({
Implements: [Meta.InhibitShortcutsDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog),
},
}, class InhibitShortcutsDialog extends GObject.Object {
+ /**
+ * @param {*} window
+ */
_init(window) {
super._init();
this._window = window;
@@ -59,7 +70,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
let permissions = {};
permissions[this._app.get_id()] = [grant];
- let data = GLib.Variant.new('av', {});
+ let data = GLib.Variant.new('av', []);
this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
true,
diff --git a/js/ui/init.js b/js/ui/init.js
index a0fe63343..6dfe9ff30 100644
--- a/js/ui/init.js
+++ b/js/ui/init.js
@@ -2,5 +2,15 @@ import { setConsoleLogDomain } from 'console';
setConsoleLogDomain('GNOME Shell');
-imports.ui.environment.init();
-imports.ui.main.start();
+import "./environment.js";
+
+import("./main.js")
+ .then(({ main }) => {
+ main.start();
+ })
+ .catch((error) => {
+ logError(error);
+ })
+ .finally(() => {
+ log("Main imported.");
+ }); \ No newline at end of file
diff --git a/js/ui/kbdA11yDialog.js b/js/ui/kbdA11yDialog.js
index a45e02443..e32480e9d 100644
--- a/js/ui/kbdA11yDialog.js
+++ b/js/ui/kbdA11yDialog.js
@@ -1,14 +1,18 @@
/* exported KbdA11yDialog */
-const { Clutter, Gio, GObject } = imports.gi;
+import Meta from 'gi://Meta';
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
-const Dialog = imports.ui.dialog;
-const ModalDialog = imports.ui.modalDialog;
+
+import * as Dialog from './dialog.js';
+import * as ModalDialog from './modalDialog.js';
const KEYBOARD_A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
const KEY_SLOW_KEYS_ENABLED = 'slowkeys-enable';
-var KbdA11yDialog = GObject.registerClass(
+export const KbdA11yDialog = GObject.registerClass(
class KbdA11yDialog extends GObject.Object {
_init() {
super._init();
@@ -25,17 +29,23 @@ class KbdA11yDialog extends GObject.Object {
let title, description;
let key, enabled;
- if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
+ const META_A11Y_SLOW_KEYS_ENABLED = 1 << 3;
+ const META_A11Y_STICKY_KEYS_ENABLED = 1 << 10;
+ // FIXME:
+ // This change https://github.com/GNOME/mutter/commit/c3acaeb25127a7520ecc0d3edbb3d0cc53b5634e#diff-8da73b762bc44dbbfb6a00938e37693e5e3fc3266673275502117ea932cf7675R55
+ // made Clutter.KeyboardA11yFlags turn into Meta.KeyboardA11yFlags but
+ // also removed it from introspection.
+ if (whatChanged & /* Meta.KeyboardA11yFlags */ META_A11Y_SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED;
- enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
+ enabled = (newFlags & META_A11Y_SLOW_KEYS_ENABLED) > 0;
title = enabled
? _("Slow Keys Turned On")
: _("Slow Keys Turned Off");
description = _('You just held down the Shift key for 8 seconds. This is the shortcut ' +
'for the Slow Keys feature, which affects the way your keyboard works.');
- } else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
+ } else if (whatChanged & META_A11Y_STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED;
- enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
+ enabled = (newFlags & META_A11Y_STICKY_KEYS_ENABLED) > 0;
title = enabled
? _("Sticky Keys Turned On")
: _("Sticky Keys Turned Off");
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index 3e188a99b..e4d43ecfa 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -1,16 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported KeyboardManager */
-
-const { Clutter, Gio, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const EdgeDragAction = imports.ui.edgeDragAction;
-const InputSourceManager = imports.ui.status.keyboard;
-const IBusManager = imports.misc.ibusManager;
-const BoxPointer = imports.ui.boxpointer;
-const Main = imports.ui.main;
-const PageIndicators = imports.ui.pageIndicators;
-const PopupMenu = imports.ui.popupMenu;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import Meta from 'gi://Meta';
+import Graphene from 'gi://Graphene';
+import * as Signals from '../misc/signals.js';
+
+import * as EdgeDragAction from './edgeDragAction.js';
+import * as InputSourceManager from './status/keyboard.js';
+import * as IBusManager from '../misc/ibusManager.js';
+import * as BoxPointer from './boxpointer.js';
+import Main from './main.js';
+import * as PageIndicators from './pageIndicators.js';
+import * as PopupMenu from './popupMenu.js';
var KEYBOARD_ANIMATION_TIME = 150;
var KEYBOARD_REST_TIME = KEYBOARD_ANIMATION_TIME * 2;
@@ -50,7 +56,7 @@ const defaultKeysPost = [
[{ action: 'emoji', icon: 'face-smile-symbolic' }, { action: 'languageMenu', extraClassName: 'layout-key', icon: 'keyboard-layout-filled-symbolic' }, { action: 'hide', extraClassName: 'hide-key', icon: 'go-down-symbolic' }]],
];
-var AspectContainer = GObject.registerClass(
+export const AspectContainer = GObject.registerClass(
class AspectContainer extends St.Widget {
_init(params) {
super._init(params);
@@ -62,6 +68,9 @@ class AspectContainer extends St.Widget {
this.queue_relayout();
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(forHeight) {
let [min, nat] = super.vfunc_get_preferred_width(forHeight);
@@ -71,6 +80,9 @@ class AspectContainer extends St.Widget {
return [min, nat];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(forWidth) {
let [min, nat] = super.vfunc_get_preferred_height(forWidth);
@@ -102,7 +114,7 @@ class AspectContainer extends St.Widget {
}
});
-var KeyContainer = GObject.registerClass(
+export const KeyContainer = GObject.registerClass(
class KeyContainer extends St.Widget {
_init() {
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
@@ -120,6 +132,8 @@ class KeyContainer extends St.Widget {
this._currentRow = null;
this._rows = [];
+
+ this.shiftKeys = [];
}
appendRow() {
@@ -183,7 +197,7 @@ class KeyContainer extends St.Widget {
}
});
-var Suggestions = GObject.registerClass(
+export const Suggestions = GObject.registerClass(
class Suggestions extends St.BoxLayout {
_init() {
super._init({
@@ -205,7 +219,7 @@ class Suggestions extends St.BoxLayout {
}
});
-var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
+export class LanguageSelectionPopup extends PopupMenu.PopupMenu {
constructor(actor) {
super(actor, 0.5, St.Side.BOTTOM);
@@ -268,7 +282,7 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
}
};
-var Key = GObject.registerClass({
+export const Key = GObject.registerClass({
Signals: {
'activated': {},
'long-press': {},
@@ -288,6 +302,7 @@ var Key = GObject.registerClass({
this.add_child(this.keyButton);
this.connect('destroy', this._onDestroy.bind(this));
+ this._keyvalPress = false;
this._extendedKeys = extendedKeys;
this._extendedKeyboard = null;
this._pressTimeoutId = 0;
@@ -516,7 +531,7 @@ var Key = GObject.registerClass({
}
});
-var KeyboardModel = class {
+export class KeyboardModel {
constructor(groupName) {
let names = [groupName];
if (groupName.includes('+'))
@@ -549,7 +564,7 @@ var KeyboardModel = class {
}
};
-var FocusTracker = class extends Signals.EventEmitter {
+export class FocusTracker extends Signals.EventEmitter {
constructor() {
super();
@@ -664,7 +679,7 @@ var FocusTracker = class extends Signals.EventEmitter {
}
};
-var EmojiPager = GObject.registerClass({
+export const EmojiPager = GObject.registerClass({
Properties: {
'delta': GObject.ParamSpec.int(
'delta', 'delta', 'delta',
@@ -952,7 +967,7 @@ var EmojiPager = GObject.registerClass({
}
});
-var EmojiSelection = GObject.registerClass({
+export const EmojiSelection = GObject.registerClass({
Signals: {
'emoji-selected': { param_types: [GObject.TYPE_STRING] },
'close-request': {},
@@ -1110,7 +1125,7 @@ var EmojiSelection = GObject.registerClass({
}
});
-var Keypad = GObject.registerClass({
+export const Keypad = GObject.registerClass({
Signals: {
'keyval': { param_types: [GObject.TYPE_UINT] },
},
@@ -1162,7 +1177,7 @@ var Keypad = GObject.registerClass({
}
});
-var KeyboardManager = class KeyBoardManager {
+export class KeyboardManager {
constructor() {
this._keyboard = null;
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
@@ -1269,7 +1284,7 @@ var KeyboardManager = class KeyBoardManager {
}
};
-var Keyboard = GObject.registerClass({
+export const Keyboard = GObject.registerClass({
Signals: {
'visibility-changed': {},
},
@@ -1301,7 +1316,7 @@ var Keyboard = GObject.registerClass({
if (!Meta.is_wayland_compositor()) {
this._connectSignal(this._focusTracker, 'focus-changed', (_tracker, focused) => {
if (focused)
- this.open(Main.layoutManager.focusIndex);
+ this.open(!!Main.layoutManager.focusIndex);
else
this.close();
});
@@ -1441,7 +1456,7 @@ var Keyboard = GObject.registerClass({
// Showing an extended key popup and clicking a key from the extended keys
// will grab focus, but ignore that
let extendedKeysWereFocused = this._focusInExtendedKeys;
- this._focusInExtendedKeys = focus && (focus._extendedKeys || focus.extendedKey);
+ this._focusInExtendedKeys = focus && (focus instanceof St.Button && (focus._extendedKeys || focus.extendedKey));
if (this._focusInExtendedKeys || extendedKeysWereFocused)
return;
@@ -1452,7 +1467,7 @@ var Keyboard = GObject.registerClass({
if (!this._showIdleId) {
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- this.open(Main.layoutManager.focusIndex);
+ this.open(!!Main.layoutManager.focusIndex);
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
@@ -1473,7 +1488,6 @@ var Keyboard = GObject.registerClass({
let level = i >= 1 && levels.length == 3 ? i + 1 : i;
let layout = new KeyContainer();
- layout.shiftKeys = [];
this._loadRows(currentLevel, level, levels.length, layout);
layers[level] = layout;
@@ -1655,6 +1669,12 @@ var Keyboard = GObject.registerClass({
this._loadDefaultKeys(post, layout, numLevels, row.length);
}
+ /**
+ * @param {*} model
+ * @param {number} level
+ * @param {number} numLevels
+ * @param {KeyContainer["prototype"]} layout
+ */
_loadRows(model, level, numLevels, layout) {
let rows = model.rows;
for (let i = 0; i < rows.length; ++i) {
@@ -1708,8 +1728,7 @@ var Keyboard = GObject.registerClass({
}
_onKeyboardGroupsChanged() {
- let nonGroupActors = [this._emojiSelection, this._keypad];
- this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
+ this._aspectContainer.get_children().filter(c => c !== this._emojiSelection && c !== this._keypad).forEach(c => {
c.destroy();
});
@@ -1747,7 +1766,7 @@ var Keyboard = GObject.registerClass({
return;
if (enabled)
- this.open(Main.layoutManager.focusIndex);
+ this.open(!!Main.layoutManager.focusIndex);
else
this.close();
}
@@ -2037,7 +2056,7 @@ var Keyboard = GObject.registerClass({
}
});
-var KeyboardController = class extends Signals.EventEmitter {
+export class KeyboardController extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 39d20e027..c4e25cc3e 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -1,21 +1,27 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported MonitorConstraint, LayoutManager */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
-const Background = imports.ui.background;
-const BackgroundMenu = imports.ui.backgroundMenu;
+import * as Background from './background.js';
+import * as BackgroundMenu from './backgroundMenu.js';
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const Ripples = imports.ui.ripples;
+import * as DND from './dnd.js';
+import Main from './main.js';
+import * as Ripples from './ripples.js';
-var STARTUP_ANIMATION_TIME = 500;
-var BACKGROUND_FADE_ANIMATION_TIME = 1000;
+export let STARTUP_ANIMATION_TIME = 500;
+export let BACKGROUND_FADE_ANIMATION_TIME = 1000;
-var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
-var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
+export let HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
+export let HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
function isPopupMetaWindow(actor) {
switch (actor.meta_window.get_window_type()) {
@@ -28,7 +34,7 @@ function isPopupMetaWindow(actor) {
}
}
-var MonitorConstraint = GObject.registerClass({
+export const MonitorConstraint = GObject.registerClass({
Properties: {
'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
@@ -44,6 +50,9 @@ var MonitorConstraint = GObject.registerClass({
false),
},
}, class MonitorConstraint extends Clutter.Constraint {
+ /**
+ * @param {*} props
+ */
_init(props) {
this._primary = false;
this._index = -1;
@@ -145,7 +154,7 @@ var MonitorConstraint = GObject.registerClass({
}
});
-var Monitor = class Monitor {
+export class Monitor {
constructor(index, geometry, geometryScale) {
this.index = index;
this.x = geometry.x;
@@ -162,11 +171,17 @@ var Monitor = class Monitor {
const UiActor = GObject.registerClass(
class UiActor extends St.Widget {
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(_forHeight) {
let width = global.stage.width;
return [width, width];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(_forWidth) {
let height = global.stage.height;
return [height, height];
@@ -179,7 +194,7 @@ const defaultParams = {
affectsInputRegion: true,
};
-var LayoutManager = GObject.registerClass({
+export const LayoutManager = GObject.registerClass({
Signals: {
'hot-corners-changed': {},
'startup-complete': {},
@@ -244,7 +259,7 @@ var LayoutManager = GObject.registerClass({
trackFullscreen: true });
this.panelBox.connect('notify::allocation',
this._panelBoxChanged.bind(this));
-
+ log('initing?');
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
layout_manager: new Clutter.BinLayout() });
this.uiGroup.add_actor(this.modalDialogGroup);
@@ -296,7 +311,7 @@ var LayoutManager = GObject.registerClass({
// This is called by Main after everything else is constructed
init() {
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
-
+ log('testing?');
this._loadBackground();
}
@@ -503,6 +518,7 @@ var LayoutManager = GObject.registerClass({
}
_panelBoxChanged() {
+ log('panel box changed')
this._updatePanelBarrier();
let size = this.panelBox.height;
@@ -532,6 +548,7 @@ var LayoutManager = GObject.registerClass({
}
_monitorsChanged() {
+ log('monitor?');
this._updateMonitors();
this._updateBoxes();
this._updateHotCorners();
@@ -606,8 +623,9 @@ var LayoutManager = GObject.registerClass({
this._systemBackground.add_constraint(constraint);
let signalId = this._systemBackground.connect('loaded', () => {
+ log('loaded!');
this._systemBackground.disconnect(signalId);
-
+log('p2');
// We're mostly prepared for the startup animation
// now, but since a lot is going on asynchronously
// during startup, let's defer the startup animation
@@ -615,6 +633,7 @@ var LayoutManager = GObject.registerClass({
// This helps to prevent us from running the animation
// when the system is bogged down
const id = GLib.idle_add(GLib.PRIORITY_LOW, () => {
+ log('idling...');
this._systemBackground.show();
global.stage.show();
this._prepareStartupAnimation();
@@ -640,6 +659,7 @@ var LayoutManager = GObject.registerClass({
// of the screen.
async _prepareStartupAnimation() {
+ log('preparing...');
// During the initial transition, add a simple actor to block all events,
// so they don't get delivered to X11 windows that have been transformed.
this._coverPane = new Clutter.Actor({ opacity: 0,
@@ -676,25 +696,31 @@ var LayoutManager = GObject.registerClass({
}
global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height);
-
+log('update backgrounds?');
await this._updateBackgrounds();
}
+ log('prepared?');
+
this.emit('startup-prepared');
this._startupAnimation();
}
_startupAnimation() {
- if (Meta.is_restart())
+ if (Meta.is_restart()) {
+ log('testing')
this._startupAnimationComplete();
- else if (Main.sessionMode.isGreeter)
+ } else if (Main.sessionMode.isGreeter)
this._startupAnimationGreeter();
- else
+ else {
+ log ('test 213');
this._startupAnimationSession();
+ }
}
_startupAnimationGreeter() {
+ log('greet start');
this.panelBox.ease({
translation_y: 0,
duration: STARTUP_ANIMATION_TIME,
@@ -704,6 +730,7 @@ var LayoutManager = GObject.registerClass({
}
_startupAnimationSession() {
+ log('greet sesh start');
const onComplete = () => this._startupAnimationComplete();
if (Main.sessionMode.hasOverview) {
Main.overview.runStartupAnimation(onComplete);
@@ -720,6 +747,7 @@ var LayoutManager = GObject.registerClass({
}
_startupAnimationComplete() {
+ log('Animation compl')
this._coverPane.destroy();
this._coverPane = null;
@@ -852,14 +880,15 @@ var LayoutManager = GObject.registerClass({
if (this._findActor(actor) != -1)
throw new Error('trying to re-track existing chrome actor');
- let actorData = { ...defaultParams, ...params };
- actorData.actor = actor;
- actorData.visibleId = actor.connect('notify::visible',
- this._queueUpdateRegions.bind(this));
- actorData.allocationId = actor.connect('notify::allocation',
- this._queueUpdateRegions.bind(this));
- actorData.destroyId = actor.connect('destroy',
- this._untrackActor.bind(this));
+ let actorData = { ...defaultParams, ...params,
+ actor: actor,
+ isibleId : actor.connect('notify::visible',
+ this._queueUpdateRegions.bind(this)),
+ allocationId : actor.connect('notify::allocation',
+ this._queueUpdateRegions.bind(this)),
+ destroyId: actor.connect('destroy',
+ this._untrackActor.bind(this)),
+ };
// Note that destroying actor will unset its parent, so we don't
// need to connect to 'destroy' too.
@@ -1069,7 +1098,7 @@ var LayoutManager = GObject.registerClass({
//
// This class manages a "hot corner" that can toggle switching to
// overview.
-var HotCorner = GObject.registerClass(
+export const HotCorner = GObject.registerClass(
class HotCorner extends Clutter.Actor {
_init(layoutManager, monitor, x, y) {
super._init();
@@ -1227,7 +1256,7 @@ class HotCorner extends Clutter.Actor {
}
});
-var PressureBarrier = class PressureBarrier extends Signals.EventEmitter {
+export class PressureBarrier extends Signals.EventEmitter {
constructor(threshold, timeout, actionMode) {
super();
diff --git a/js/ui/lightbox.js b/js/ui/lightbox.js
index 9e66ffd58..3fb71ab40 100644
--- a/js/ui/lightbox.js
+++ b/js/ui/lightbox.js
@@ -1,12 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Lightbox */
-const { Clutter, GObject, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-var DEFAULT_FADE_FACTOR = 0.4;
-var VIGNETTE_BRIGHTNESS = 0.5;
-var VIGNETTE_SHARPNESS = 0.7;
+export let DEFAULT_FADE_FACTOR = 0.4;
+export let VIGNETTE_BRIGHTNESS = 0.5;
+export let VIGNETTE_SHARPNESS = 0.7;
const VIGNETTE_DECLARATIONS = '\
uniform float brightness;\n\
@@ -21,7 +24,7 @@ t = clamp(t, 0.0, 1.0);\n\
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
-var RadialShaderEffect = GObject.registerClass({
+export const RadialShaderEffect = GObject.registerClass({
Properties: {
'brightness': GObject.ParamSpec.float(
'brightness', 'brightness', 'brightness',
@@ -102,7 +105,7 @@ var RadialShaderEffect = GObject.registerClass({
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height in @params.
*/
-var Lightbox = GObject.registerClass({
+export const Lightbox = GObject.registerClass({
Properties: {
'active': GObject.ParamSpec.boolean(
'active', 'active', 'active', GObject.ParamFlags.READABLE, false),
diff --git a/js/ui/locatePointer.js b/js/ui/locatePointer.js
index 6ae29419a..41ccf3468 100644
--- a/js/ui/locatePointer.js
+++ b/js/ui/locatePointer.js
@@ -1,14 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LocatePointer */
-const { Gio } = imports.gi;
-const Ripples = imports.ui.ripples;
-const Main = imports.ui.main;
+import Gio from 'gi://Gio';
+import * as Ripples from './ripples.js';
+import Main from './main.js';
const LOCATE_POINTER_KEY = "locate-pointer";
const LOCATE_POINTER_SCHEMA = "org.gnome.desktop.interface";
-var LocatePointer = class {
+export class LocatePointer {
constructor() {
this._settings = new Gio.Settings({ schema_id: LOCATE_POINTER_SCHEMA });
this._settings.connect(`changed::${LOCATE_POINTER_KEY}`, () => this._syncEnabled());
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index 3a39b7de9..d3798613b 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -1,16 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */
-const { Clutter, Cogl, Gio, GLib, GObject,
- Graphene, Meta, Pango, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-const System = imports.system;
-
-const History = imports.misc.history;
-const ExtensionUtils = imports.misc.extensionUtils;
-const ShellEntry = imports.ui.shellEntry;
-const Main = imports.ui.main;
-const JsParse = imports.misc.jsParse;
+import Clutter from 'gi://Clutter';
+import Cogl from 'gi://Cogl';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Graphene from 'gi://Graphene';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
+import System from 'system';
+
+import * as History from '../misc/history.js';
+import * as ExtensionUtils from '../misc/extensionUtils.js';
+import * as ShellEntry from './shellEntry.js';
+import Main from './main.js';
+import * as JsParse from '../misc/jsParse.js';
const { ExtensionState } = ExtensionUtils;
@@ -18,7 +26,7 @@ const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
- 'const Main = imports.ui.main; ' +
+ 'const Main = getMain(); ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
'const stage = global.stage; ' +
@@ -29,9 +37,10 @@ var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = im
const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event
-var AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
-var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 200;
-var AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
+
+export let AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
+export let AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 200;
+export let AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
const LG_ANIMATION_TIME = 500;
@@ -45,7 +54,7 @@ function _getAutoCompleteGlobalKeywords() {
return keywords.concat(windowProperties).concat(headerProperties);
}
-var AutoComplete = class AutoComplete extends Signals.EventEmitter {
+export class AutoComplete extends Signals.EventEmitter {
constructor(entry) {
super();
@@ -109,8 +118,7 @@ var AutoComplete = class AutoComplete extends Signals.EventEmitter {
}
};
-
-var Notebook = GObject.registerClass({
+export const Notebook = GObject.registerClass({
Signals: { 'selection': { param_types: [Clutter.Actor.$gtype] } },
}, class Notebook extends St.BoxLayout {
_init() {
@@ -253,8 +261,14 @@ function objectToString(o) {
}
}
-var ObjLink = GObject.registerClass(
+export const ObjLink = GObject.registerClass(
+/** @extends {St.Button<Clutter.Text>} */
class ObjLink extends St.Button {
+ /**
+ * @param {*} lookingGlass
+ * @param {*} o
+ * @param {*} title
+ */
_init(lookingGlass, o, title) {
let text;
if (title)
@@ -281,8 +295,14 @@ class ObjLink extends St.Button {
}
});
-var Result = GObject.registerClass(
+export const Result = GObject.registerClass(
class Result extends St.BoxLayout {
+ /**
+ * @param {*} lookingGlass
+ * @param {*} command
+ * @param {*} o
+ * @param {*} index
+ */
_init(lookingGlass, command, o, index) {
super._init({ vertical: true });
@@ -304,8 +324,11 @@ class Result extends St.BoxLayout {
}
});
-var WindowList = GObject.registerClass({
+export const WindowList = GObject.registerClass({
}, class WindowList extends St.BoxLayout {
+ /**
+ * @param {*} lookingGlass
+ */
_init(lookingGlass) {
super._init({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default();
@@ -357,8 +380,11 @@ var WindowList = GObject.registerClass({
}
});
-var ObjInspector = GObject.registerClass(
+export const ObjInspector = GObject.registerClass(
class ObjInspector extends St.ScrollView {
+ /**
+ * @param {*} lookingGlass
+ */
_init(lookingGlass) {
super._init({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
@@ -397,7 +423,8 @@ class ObjInspector extends St.ScrollView {
text: 'Inspecting: %s: %s'.format(typeof obj, objectToString(obj)),
x_expand: true,
});
- label.single_line_mode = true;
+ // TODO: Is this the intended code?
+ label.clutterText.single_line_mode = true;
hbox.add_child(label);
let button = new St.Button({ label: 'Insert', style_class: 'lg-obj-inspector-button' });
button.connect('clicked', this._onInsert.bind(this));
@@ -475,7 +502,7 @@ class ObjInspector extends St.ScrollView {
}
});
-var RedBorderEffect = GObject.registerClass(
+export const RedBorderEffect = GObject.registerClass(
class RedBorderEffect extends Clutter.Effect {
_init() {
super._init();
@@ -527,7 +554,7 @@ class RedBorderEffect extends Clutter.Effect {
}
});
-var Inspector = GObject.registerClass({
+export const Inspector = GObject.registerClass({
Signals: { 'closed': {},
'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
}, class Inspector extends Clutter.Actor {
@@ -667,7 +694,7 @@ var Inspector = GObject.registerClass({
}
});
-var Extensions = GObject.registerClass({
+export const Extensions = GObject.registerClass({
}, class Extensions extends St.BoxLayout {
_init(lookingGlass) {
super._init({ vertical: true, name: 'lookingGlassExtensions' });
@@ -820,7 +847,7 @@ var Extensions = GObject.registerClass({
});
-var ActorLink = GObject.registerClass({
+export const ActorLink = GObject.registerClass({
Signals: {
'inspect-actor': {},
},
@@ -877,7 +904,7 @@ var ActorLink = GObject.registerClass({
}
});
-var ActorTreeViewer = GObject.registerClass(
+export const ActorTreeViewer = GObject.registerClass(
class ActorTreeViewer extends St.BoxLayout {
_init(lookingGlass) {
super._init();
@@ -1004,7 +1031,7 @@ class ActorTreeViewer extends St.BoxLayout {
}
});
-var LookingGlass = GObject.registerClass(
+export const LookingGlass = GObject.registerClass(
class LookingGlass extends St.BoxLayout {
_init() {
super._init({
@@ -1093,6 +1120,7 @@ class LookingGlass extends St.BoxLayout {
this._evalBox = new St.BoxLayout({ name: 'EvalBox', vertical: true });
notebook.appendPage('Evaluator', this._evalBox);
+ /** @type {St.BoxLayout<Result["prototype"]>} */
this._resultsArea = new St.BoxLayout({
name: 'ResultsArea',
vertical: true,
@@ -1270,7 +1298,7 @@ class LookingGlass extends St.BoxLayout {
getResult(idx) {
try {
- return this._resultsArea.get_child_at_index(idx - this._offset).o;
+ return /** @type {Result["prototype"]} */ (this._resultsArea.get_child_at_index(idx - this._offset)).o;
} catch (e) {
throw new Error('Unknown result at index %d'.format(idx));
}
diff --git a/js/ui/magnifier.js b/js/ui/magnifier.js
index 8727dbd67..ff8876a32 100644
--- a/js/ui/magnifier.js
+++ b/js/ui/magnifier.js
@@ -1,19 +1,28 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Magnifier */
-const { Atspi, Clutter, GDesktopEnums,
- Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
+import Atspi from 'gi://Atspi';
+import Clutter from 'gi://Clutter';
+import GDesktopEnums from 'gi://GDesktopEnums';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Background = imports.ui.background;
-const FocusCaretTracker = imports.ui.focusCaretTracker;
-const Main = imports.ui.main;
-const PointerWatcher = imports.ui.pointerWatcher;
+import * as Signals from '../misc/signals.js';
-var CROSSHAIRS_CLIP_SIZE = [100, 100];
-var NO_CHANGE = 0.0;
+import * as Background from './background.js';
+import * as FocusCaretTracker from './focusCaretTracker.js';
+import Main from './main.js';
+import * as PointerWatcher from './pointerWatcher.js';
-var POINTER_REST_TIME = 1000; // milliseconds
+/** @type {[number, number]} */
+export const CROSSHAIRS_CLIP_SIZE = [100, 100];
+export const NO_CHANGE = 0.0;
+
+export const POINTER_REST_TIME = 1000; // milliseconds
// Settings
const MAGNIFIER_SCHEMA = 'org.gnome.desktop.a11y.magnifier';
@@ -39,7 +48,7 @@ const CROSS_HAIRS_OPACITY_KEY = 'cross-hairs-opacity';
const CROSS_HAIRS_LENGTH_KEY = 'cross-hairs-length';
const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
-var MouseSpriteContent = GObject.registerClass({
+export const MouseSpriteContent = GObject.registerClass({
Implements: [Clutter.Content],
}, class MouseSpriteContent extends GObject.Object {
_init() {
@@ -72,6 +81,9 @@ var MouseSpriteContent = GObject.registerClass({
return this._texture;
}
+ /**
+ * @this {this & Clutter.Content}
+ */
set texture(coglTexture) {
if (this._texture == coglTexture)
return;
@@ -87,7 +99,7 @@ var MouseSpriteContent = GObject.registerClass({
}
});
-var Magnifier = class Magnifier extends Signals.EventEmitter {
+export class Magnifier extends Signals.EventEmitter {
constructor() {
super();
@@ -98,8 +110,10 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
let cursorTracker = Meta.CursorTracker.get_for_display(global.display);
this._cursorTracker = cursorTracker;
- this._mouseSprite = new Clutter.Actor({ request_mode: Clutter.RequestMode.CONTENT_SIZE });
- this._mouseSprite.content = new MouseSpriteContent();
+ this._mouseSprite = new Clutter.Actor({
+ request_mode: Clutter.RequestMode.CONTENT_SIZE,
+ content: new MouseSpriteContent()
+ });
// Create the first ZoomRegion and initialize it according to the
// magnification settings.
@@ -145,7 +159,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* setActive:
* Show/hide all the zoom regions.
- * @param {bool} activate: Boolean to activate or de-activate the magnifier.
+ * @param {boolean} activate: Boolean to activate or de-activate the magnifier.
*/
setActive(activate) {
let isActive = this.isActive();
@@ -185,7 +199,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* isActive:
- * @returns {bool} Whether the magnifier is active.
+ * @returns {boolean} Whether the magnifier is active.
*/
isActive() {
// Sufficient to check one ZoomRegion since Magnifier's active
@@ -220,7 +234,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* isTrackingMouse:
- * @returns {bool} whether the magnifier is currently tracking the mouse
+ * @returns {boolean} whether the magnifier is currently tracking the mouse
*/
isTrackingMouse() {
return !!this._pointerWatch;
@@ -297,7 +311,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* getZoomRegions:
* Return a list of ZoomRegion's for this Magnifier.
- * @returns {number[]} The Magnifier's zoom region list.
+ * @returns {ZoomRegion[]} The Magnifier's zoom region list.
*/
getZoomRegions() {
return this._zoomRegions;
@@ -345,7 +359,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* setCrosshairsVisible:
* Show or hide the cross hair.
- * @param {bool} visible: Flag that indicates show (true) or hide (false).
+ * @param {boolean} visible: Flag that indicates show (true) or hide (false).
*/
setCrosshairsVisible(visible) {
if (visible) {
@@ -406,17 +420,6 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
}
/**
- * getCrosshairsOpacity:
- * @returns {number} Value between 0.0 (transparent) and 1.0 (fully opaque).
- */
- getCrosshairsOpacity() {
- if (this._crossHairs)
- return this._crossHairs.getOpacity() / 255.0;
- else
- return 0.0;
- }
-
- /**
* setCrosshairsLength:
* Set the crosshairs length for all ZoomRegions.
* @param {number} length: The length of the vertical and horizontal
@@ -445,7 +448,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* setCrosshairsClip:
* Set whether the crosshairs are clipped at their intersection.
- * @param {bool} clip: Flag to indicate whether to clip the crosshairs.
+ * @param {boolean} clip: Flag to indicate whether to clip the crosshairs.
*/
setCrosshairsClip(clip) {
if (!this._crossHairs)
@@ -458,7 +461,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
/**
* getCrosshairsClip:
* Get whether the crosshairs are clipped by the mouse image.
- * @returns {bool} Whether the crosshairs are clipped.
+ * @returns {boolean} Whether the crosshairs are clipped.
*/
getCrosshairsClip() {
if (this._crossHairs) {
@@ -577,9 +580,9 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
if (aPref)
zoomRegion.setCaretTrackingMode(aPref);
- aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
- if (aPref)
- zoomRegion.setInvertLightness(aPref);
+ let aBoolPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
+ if (aBoolPref)
+ zoomRegion.setInvertLightness(aBoolPref);
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
if (aPref)
@@ -698,7 +701,7 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
}
};
-var ZoomRegion = class ZoomRegion {
+export class ZoomRegion {
constructor(magnifier, mouseSourceActor) {
this._magnifier = magnifier;
this._focusCaretTracker = new FocusCaretTracker.FocusCaretTracker();
@@ -749,11 +752,11 @@ var ZoomRegion = class ZoomRegion {
this._monitorsChanged.bind(this));
this._signalConnections.push([Main.layoutManager, id]);
- id = this._focusCaretTracker.connect('caret-moved', this._updateCaret.bind(this));
- this._signalConnections.push([this._focusCaretTracker, id]);
+ let focusId = this._focusCaretTracker.connect('caret-moved', this._updateCaret.bind(this));
+ this._signalConnections.push([this._focusCaretTracker, focusId]);
- id = this._focusCaretTracker.connect('focus-changed', this._updateFocus.bind(this));
- this._signalConnections.push([this._focusCaretTracker, id]);
+ focusId = this._focusCaretTracker.connect('focus-changed', this._updateFocus.bind(this));
+ this._signalConnections.push([this._focusCaretTracker, focusId]);
}
_disconnectSignals() {
@@ -827,7 +830,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setActive:
- * @param {bool} activate: Boolean to show/hide the ZoomRegion.
+ * @param {boolean} activate: Boolean to show/hide the ZoomRegion.
*/
setActive(activate) {
if (activate == this.isActive())
@@ -854,7 +857,7 @@ var ZoomRegion = class ZoomRegion {
/**
* isActive:
- * @returns {bool} Whether this ZoomRegion is active
+ * @returns {boolean} Whether this ZoomRegion is active
*/
isActive() {
return this._magView != null;
@@ -993,7 +996,7 @@ var ZoomRegion = class ZoomRegion {
* setLensMode:
* Turn lens mode on/off. In full screen mode, lens mode does nothing since
* a lens the size of the screen is pointless.
- * @param {bool} lensMode: Whether lensMode should be active
+ * @param {boolean} lensMode: Whether lensMode should be active
*/
setLensMode(lensMode) {
this._lensMode = lensMode;
@@ -1004,7 +1007,7 @@ var ZoomRegion = class ZoomRegion {
/**
* isLensMode:
* Is lens mode on or off?
- * @returns {bool} The lens mode state.
+ * @returns {boolean} The lens mode state.
*/
isLensMode() {
return this._lensMode;
@@ -1014,7 +1017,7 @@ var ZoomRegion = class ZoomRegion {
* setClampScrollingAtEdges:
* Stop vs. allow scrolling of the magnified contents when it scroll beyond
* the edges of the screen.
- * @param {bool} clamp: Boolean to turn on/off clamping.
+ * @param {boolean} clamp: Boolean to turn on/off clamping.
*/
setClampScrollingAtEdges(clamp) {
this._clampScrollingAtEdges = clamp;
@@ -1140,7 +1143,7 @@ var ZoomRegion = class ZoomRegion {
/**
* scrollToMousePos:
* Set the region of interest based on the position of the system pointer.
- * @returns {bool}: Whether the system mouse pointer is over the
+ * @returns {boolean}: Whether the system mouse pointer is over the
* magnified view.
*/
scrollToMousePos() {
@@ -1200,7 +1203,7 @@ var ZoomRegion = class ZoomRegion {
/**
* addCrosshairs:
* Add crosshairs centered on the magnified mouse.
- * @param {Crosshairs} crossHairs: Crosshairs instance
+ * @param {Crosshairs["prototype"]} crossHairs: Crosshairs instance
*/
addCrosshairs(crossHairs) {
this._crossHairs = crossHairs;
@@ -1214,7 +1217,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setInvertLightness:
* Set whether to invert the lightness of the magnified view.
- * @param {bool} flag: whether brightness should be inverted
+ * @param {boolean} flag: whether brightness should be inverted
*/
setInvertLightness(flag) {
this._invertLightness = flag;
@@ -1225,7 +1228,7 @@ var ZoomRegion = class ZoomRegion {
/**
* getInvertLightness:
* Retrieve whether the lightness is inverted.
- * @returns {bool} whether brightness should be inverted
+ * @returns {boolean} whether brightness should be inverted
*/
getInvertLightness() {
return this._invertLightness;
@@ -1650,7 +1653,7 @@ var ZoomRegion = class ZoomRegion {
}
};
-var Crosshairs = GObject.registerClass(
+export const Crosshairs = GObject.registerClass(
class Crosshairs extends Clutter.Actor {
_init() {
// Set the group containing the crosshairs to three times the desktop
@@ -1825,7 +1828,7 @@ class Crosshairs extends Clutter.Actor {
* setClip:
* Set the width and height of the rectangle that clips the crosshairs at
* their intersection
- * @param {number[]} size: Array of [width, height] defining the size
+ * @param {[number, number]} size: Array of [width, height] defining the size
* of the clip rectangle.
*/
setClip(size) {
@@ -1841,12 +1844,16 @@ class Crosshairs extends Clutter.Actor {
}
}
+ getClip() {
+ return this._clipSize;
+ }
+
/**
* reCenter:
* Reposition the horizontal and vertical hairs such that they cross at
* the center of crosshairs group. If called with the dimensions of
* the clip rectangle, these are used to update the size of the clip.
- * @param {number[]=} clipSize: If present, the clip's [width, height].
+ * @param {[number, number]} [clipSize]: If present, the clip's [width, height].
*/
reCenter(clipSize) {
let [groupWidth, groupHeight] = this.get_size();
@@ -1871,7 +1878,7 @@ class Crosshairs extends Clutter.Actor {
}
});
-var MagShaderEffects = class MagShaderEffects {
+export class MagShaderEffects {
constructor(uiGroupClone) {
this._inverse = new Shell.InvertLightnessEffect();
this._brightnessContrast = new Clutter.BrightnessContrastEffect();
@@ -1902,7 +1909,7 @@ var MagShaderEffects = class MagShaderEffects {
/**
* setInvertLightness:
* Enable/disable invert lightness effect.
- * @param {bool} invertFlag: Enabled flag.
+ * @param {boolean} invertFlag: Enabled flag.
*/
setInvertLightness(invertFlag) {
this._inverse.set_enabled(invertFlag);
diff --git a/js/ui/main.js b/js/ui/main.js
index 1069674ae..e848eb070 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -7,47 +7,54 @@
kbdA11yDialog, introspectService, start, pushModal, popModal,
activateWindow, createLookingGlass, initializeDeferredWork,
getThemeStylesheet, setThemeStylesheet */
-
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const AccessDialog = imports.ui.accessDialog;
-const AudioDeviceSelection = imports.ui.audioDeviceSelection;
-const Components = imports.ui.components;
-const CtrlAltTab = imports.ui.ctrlAltTab;
-const EndSessionDialog = imports.ui.endSessionDialog;
-const ExtensionSystem = imports.ui.extensionSystem;
-const ExtensionDownloader = imports.ui.extensionDownloader;
-const InputMethod = imports.misc.inputMethod;
-const Introspect = imports.misc.introspect;
-const Keyboard = imports.ui.keyboard;
-const MessageTray = imports.ui.messageTray;
-const ModalDialog = imports.ui.modalDialog;
-const OsdWindow = imports.ui.osdWindow;
-const OsdMonitorLabeler = imports.ui.osdMonitorLabeler;
-const Overview = imports.ui.overview;
-const PadOsd = imports.ui.padOsd;
-const Panel = imports.ui.panel;
-const RunDialog = imports.ui.runDialog;
-const WelcomeDialog = imports.ui.welcomeDialog;
-const Layout = imports.ui.layout;
-const LoginManager = imports.misc.loginManager;
-const LookingGlass = imports.ui.lookingGlass;
-const NotificationDaemon = imports.ui.notificationDaemon;
-const WindowAttentionHandler = imports.ui.windowAttentionHandler;
-const ScreenShield = imports.ui.screenShield;
-const Scripting = imports.ui.scripting;
-const SessionMode = imports.ui.sessionMode;
-const ShellDBus = imports.ui.shellDBus;
-const ShellMountOperation = imports.ui.shellMountOperation;
-const WindowManager = imports.ui.windowManager;
-const Magnifier = imports.ui.magnifier;
-const XdndHandler = imports.ui.xdndHandler;
-const KbdA11yDialog = imports.ui.kbdA11yDialog;
-const LocatePointer = imports.ui.locatePointer;
-const PointerA11yTimeout = imports.ui.pointerA11yTimeout;
-const ParentalControlsManager = imports.misc.parentalControlsManager;
+// @ts-check
+
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AccessDialog from './accessDialog.js';
+import * as AudioDeviceSelection from './audioDeviceSelection.js';
+import * as Components from './components.js';
+import * as CtrlAltTab from './ctrlAltTab.js';
+import * as EndSessionDialog from './endSessionDialog.js';
+import * as InputMethod from '../misc/inputMethod.js';
+import * as Introspect from '../misc/introspect.js';
+import * as Keyboard from './keyboard.js';
+import * as MessageTray from './messageTray.js';
+import * as ModalDialog from './modalDialog.js';
+import * as OsdWindow from './osdWindow.js';
+import * as OsdMonitorLabeler from './osdMonitorLabeler.js';
+import * as Overview from './overview.js';
+import * as PadOsd from './padOsd.js';
+import * as Panel from './panel.js';
+import * as Params from '../misc/params.js';
+import * as RunDialog from './runDialog.js';
+import * as WelcomeDialog from './welcomeDialog.js';
+import * as Layout from './layout.js';
+import * as LoginManager from '../misc/loginManager.js';
+import * as LookingGlass from './lookingGlass.js';
+import * as NotificationDaemon from './notificationDaemon.js';
+import * as WindowAttentionHandler from './windowAttentionHandler.js';
+import * as ScreenShield from './screenShield.js';
+import * as Scripting from './scripting.js';
+import * as SessionMode from './sessionMode.js';
+import * as ShellDBus from './shellDBus.js';
+import * as ShellMountOperation from './shellMountOperation.js';
+import * as WindowManager from './windowManager.js';
+import * as Magnifier from './magnifier.js';
+import * as XdndHandler from './xdndHandler.js';
+import * as KbdA11yDialog from './kbdA11yDialog.js';
+import * as LocatePointer from './locatePointer.js';
+import * as PointerA11yTimeout from './pointerA11yTimeout.js';
+import * as ParentalControlsManager from '../misc/parentalControlsManager.js';
const Config = imports.misc.config;
-const Util = imports.misc.util;
+import * as Util from '../misc/util.js';
+import * as ExtensionUtils from '../misc/extensionUtils.js';
const WELCOME_DIALOG_LAST_SHOWN_VERSION = 'welcome-dialog-last-shown-version';
// Make sure to mention the point release, otherwise it will show every time
@@ -56,777 +63,823 @@ const WELCOME_DIALOG_LAST_TOUR_CHANGE = '40.beta';
const LOG_DOMAIN = 'GNOME Shell';
const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
-var componentManager = null;
-var extensionManager = null;
-var panel = null;
-var overview = null;
-var runDialog = null;
-var lookingGlass = null;
-var welcomeDialog = null;
-var wm = null;
-var messageTray = null;
-var screenShield = null;
-var notificationDaemon = null;
-var windowAttentionHandler = null;
-var ctrlAltTabManager = null;
-var padOsdService = null;
-var osdWindowManager = null;
-var osdMonitorLabeler = null;
-var sessionMode = null;
-var shellAccessDialogDBusService = null;
-var shellAudioSelectionDBusService = null;
-var shellDBusService = null;
-var shellMountOpDBusService = null;
-var screenSaverDBus = null;
-var modalCount = 0;
-var actionMode = Shell.ActionMode.NONE;
-var modalActorFocusStack = [];
-var uiGroup = null;
-var magnifier = null;
-var xdndHandler = null;
-var keyboard = null;
-var layoutManager = null;
-var kbdA11yDialog = null;
-var inputMethod = null;
-var introspectService = null;
-var locatePointer = null;
-let _startDate;
-let _defaultCssStylesheet = null;
-let _cssStylesheet = null;
-let _themeResource = null;
-let _oskResource = null;
-
-Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
-Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
-
-let _remoteAccessInhibited = false;
-
-function _sessionUpdated() {
- if (sessionMode.isPrimary)
- _loadDefaultStylesheet();
-
- wm.allowKeybinding('overlay-key', Shell.ActionMode.NORMAL |
- Shell.ActionMode.OVERVIEW);
-
- wm.allowKeybinding('locate-pointer-key', Shell.ActionMode.ALL);
-
- wm.setCustomKeybindingHandler('panel-run-dialog',
- Shell.ActionMode.NORMAL |
- Shell.ActionMode.OVERVIEW,
- sessionMode.hasRunDialog ? openRunDialog : null);
-
- if (!sessionMode.hasRunDialog) {
- if (runDialog)
- runDialog.close();
- if (lookingGlass)
- lookingGlass.close();
- if (welcomeDialog)
- welcomeDialog.close();
- }
-
- let remoteAccessController = global.backend.get_remote_access_controller();
- if (remoteAccessController) {
- if (sessionMode.allowScreencast && _remoteAccessInhibited) {
- remoteAccessController.uninhibit_remote_access();
- _remoteAccessInhibited = false;
- } else if (!sessionMode.allowScreencast && !_remoteAccessInhibited) {
- remoteAccessController.inhibit_remote_access();
- _remoteAccessInhibited = true;
+export class Main {
+ componentManager = null;
+ extensionManager = null;
+ panel = null;
+ overview = null;
+ runDialog = null;
+ lookingGlass = null;
+ welcomeDialog = null;
+ /** @type {WindowManager.WindowManager} */
+ wm = null;
+ messageTray = null;
+ screenShield = null;
+ notificationDaemon = null;
+ windowAttentionHandler = null;
+ /** @type {CtrlAltTab.CtrlAltTabManager} */
+ ctrlAltTabManager = null;
+ padOsdService = null;
+ osdWindowManager = null;
+ osdMonitorLabeler = null;
+ sessionMode = null;
+ shellAccessDialogDBusService = null;
+ shellAudioSelectionDBusService = null;
+ shellDBusService = null;
+ shellMountOpDBusService = null;
+ screenSaverDBus = null;
+ modalCount = 0;
+ actionMode = Shell.ActionMode.NONE;
+ modalActorFocusStack = [];
+ uiGroup = null;
+ /** @type {Magnifier.Magnifier} */
+ magnifier = null;
+ /** @type {XdndHandler.XdndHandler} */
+ xdndHandler = null;
+ keyboard = null;
+ /** @type {Layout.LayoutManager["prototype"]} */
+ layoutManager = null;
+ kbdA11yDialog = null;
+ inputMethod = null;
+ introspectService = null;
+ locatePointer = null;
+ _startDate;
+ _defaultCssStylesheet = null;
+ _cssStylesheet = null;
+ _themeResource = null;
+ _oskResource = null;
+
+ _remoteAccessInhibited = false;
+
+ _sessionUpdated() {
+ const { wm, sessionMode, welcomeDialog, overview, runDialog, lookingGlass } = this;
+
+ if (sessionMode.isPrimary)
+ this._loadDefaultStylesheet();
+
+
+ wm.setCustomKeybindingHandler('panel-main-menu',
+ Shell.ActionMode.NORMAL |
+ Shell.ActionMode.OVERVIEW,
+ sessionMode.hasOverview ? overview.toggle.bind(overview) : null);
+ wm.allowKeybinding('overlay-key', Shell.ActionMode.NORMAL |
+ Shell.ActionMode.OVERVIEW);
+
+ wm.allowKeybinding('locate-pointer-key', Shell.ActionMode.ALL);
+
+ wm.setCustomKeybindingHandler('panel-run-dialog',
+ Shell.ActionMode.NORMAL |
+ Shell.ActionMode.OVERVIEW,
+ sessionMode.hasRunDialog ? this.openRunDialog : null);
+
+ if (!sessionMode.hasRunDialog) {
+ if (runDialog)
+ runDialog.close();
+ if (lookingGlass)
+ lookingGlass.close();
+ if (welcomeDialog)
+ welcomeDialog.close();
+ }
+
+ let remoteAccessController = global.backend.get_remote_access_controller();
+ if (remoteAccessController) {
+ if (sessionMode.allowScreencast && this._remoteAccessInhibited) {
+ remoteAccessController.uninhibit_remote_access();
+ this._remoteAccessInhibited = false;
+ } else if (!sessionMode.allowScreencast && !this._remoteAccessInhibited) {
+ remoteAccessController.inhibit_remote_access();
+ this._remoteAccessInhibited = true;
+ }
}
- }
-}
-
-function start() {
- // These are here so we don't break compatibility.
- global.logError = globalThis.log;
- global.log = globalThis.log;
-
- // Chain up async errors reported from C
- global.connect('notify-error', (global, msg, detail) => {
- notifyError(msg, detail);
- });
-
- let currentDesktop = GLib.getenv('XDG_CURRENT_DESKTOP');
- if (!currentDesktop || !currentDesktop.split(':').includes('GNOME'))
- Gio.DesktopAppInfo.set_desktop_env('GNOME');
-
- sessionMode = new SessionMode.SessionMode();
- sessionMode.connect('updated', _sessionUpdated);
-
- St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
-
- // Initialize ParentalControlsManager before the UI
- ParentalControlsManager.getDefault();
-
- _initializeUI();
-
- shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
- shellAudioSelectionDBusService = new AudioDeviceSelection.AudioDeviceSelectionDBus();
- shellDBusService = new ShellDBus.GnomeShell();
- shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();
-
- const watchId = Gio.DBus.session.watch_name('org.gnome.Shell.Notifications',
- Gio.BusNameWatcherFlags.AUTO_START,
- bus => bus.unwatch_name(watchId),
- bus => bus.unwatch_name(watchId));
-
- _sessionUpdated();
-}
-
-function _initializeUI() {
- // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
- // also initialize ShellAppSystem first. ShellAppSystem
- // needs to load all the .desktop files, and ShellWindowTracker
- // will use those to associate with windows. Right now
- // the Monitor doesn't listen for installed app changes
- // and recalculate application associations, so to avoid
- // races for now we initialize it here. It's better to
- // be predictable anyways.
- Shell.WindowTracker.get_default();
- Shell.AppUsage.get_default();
-
- reloadThemeResource();
- _loadOskLayouts();
- _loadDefaultStylesheet();
-
- new AnimationsSettings();
-
- // Setup the stage hierarchy early
- layoutManager = new Layout.LayoutManager();
-
- // Various parts of the codebase still refer to Main.uiGroup
- // instead of using the layoutManager. This keeps that code
- // working until it's updated.
- uiGroup = layoutManager.uiGroup;
-
- padOsdService = new PadOsd.PadOsdService();
- xdndHandler = new XdndHandler.XdndHandler();
- ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
- osdWindowManager = new OsdWindow.OsdWindowManager();
- osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
- overview = new Overview.Overview();
- kbdA11yDialog = new KbdA11yDialog.KbdA11yDialog();
- wm = new WindowManager.WindowManager();
- magnifier = new Magnifier.Magnifier();
- locatePointer = new LocatePointer.LocatePointer();
-
- if (LoginManager.canLock())
- screenShield = new ScreenShield.ScreenShield();
-
- inputMethod = new InputMethod.InputMethod();
- Clutter.get_default_backend().set_input_method(inputMethod);
-
- messageTray = new MessageTray.MessageTray();
- panel = new Panel.Panel();
- keyboard = new Keyboard.KeyboardManager();
- notificationDaemon = new NotificationDaemon.NotificationDaemon();
- windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
- componentManager = new Components.ComponentManager();
-
- introspectService = new Introspect.IntrospectService();
-
- layoutManager.init();
- overview.init();
-
- new PointerA11yTimeout.PointerA11yTimeout();
-
- global.connect('locate-pointer', () => {
- locatePointer.show();
- });
-
- global.display.connect('show-restart-message', (display, message) => {
- showRestartMessage(message);
- return true;
- });
-
- global.display.connect('restart', () => {
- global.reexec_self();
- return true;
- });
-
- global.display.connect('gl-video-memory-purged', loadTheme);
-
- // Provide the bus object for gnome-session to
- // initiate logouts.
- EndSessionDialog.init();
-
- // We're ready for the session manager to move to the next phase
- GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
- Shell.util_sd_notify();
- global.context.notify_ready();
- return GLib.SOURCE_REMOVE;
- });
-
- _startDate = new Date();
-
- ExtensionDownloader.init();
- extensionManager = new ExtensionSystem.ExtensionManager();
- extensionManager.init();
- if (sessionMode.isGreeter && screenShield) {
- layoutManager.connect('startup-prepared', () => {
- screenShield.showDialog();
+ log('session updated...');
+ }
+
+ start() {
+ // These are here so we don't break compatibility.
+ global.logError = globalThis.log;
+ global.log = globalThis.log;
+
+ // Chain up async errors reported from C
+ global.connect('notify-error', (global, msg, detail) => {
+ this.notifyError(msg, detail);
});
+
+ let currentDesktop = GLib.getenv('XDG_CURRENT_DESKTOP');
+ if (!currentDesktop || !currentDesktop.split(':').includes('GNOME'))
+ Gio.DesktopAppInfo.set_desktop_env('GNOME');
+
+ this.sessionMode = new SessionMode.SessionMode();
+ this.sessionMode.connect('updated', this._sessionUpdated);
+
+ St.Settings.get().connect('notify::gtk-theme', this._loadDefaultStylesheet);
+
+ // Initialize ParentalControlsManager before the UI
+ ParentalControlsManager.getDefault();
+
+ this._initializeUI();
+
+ this.shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
+ this.shellAudioSelectionDBusService = new AudioDeviceSelection.AudioDeviceSelectionDBus();
+ this.shellDBusService = new ShellDBus.GnomeShell();
+ this.shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();
+
+ const watchId = Gio.DBus.session.watch_name('org.gnome.Shell.Notifications',
+ Gio.BusNameWatcherFlags.AUTO_START,
+ bus => bus.unwatch_name(watchId),
+ bus => bus.unwatch_name(watchId));
+
+ this._sessionUpdated();
+
+ log("Started...");
}
-
- layoutManager.connect('startup-complete', () => {
- if (actionMode == Shell.ActionMode.NONE)
- actionMode = Shell.ActionMode.NORMAL;
-
- if (screenShield)
- screenShield.lockIfWasLocked();
-
- if (sessionMode.currentMode != 'gdm' &&
- sessionMode.currentMode != 'initial-setup') {
- GLib.log_structured(LOG_DOMAIN, GLib.LogLevelFlags.LEVEL_MESSAGE, {
- 'MESSAGE': 'GNOME Shell started at %s'.format(_startDate),
- 'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID,
+
+ _initializeUI() {
+ // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
+ // also initialize ShellAppSystem first. ShellAppSystem
+ // needs to load all the .desktop files, and ShellWindowTracker
+ // will use those to associate with windows. Right now
+ // the Monitor doesn't listen for installed app changes
+ // and recalculate application associations, so to avoid
+ // races for now we initialize it here. It's better to
+ // be predictable anyways.
+ Shell.WindowTracker.get_default();
+ Shell.AppUsage.get_default();
+
+ this.reloadThemeResource();
+ this._loadOskLayouts();
+ this._loadDefaultStylesheet();
+
+ new AnimationsSettings();
+
+ // Setup the stage hierarchy early
+ this.layoutManager = new Layout.LayoutManager();
+
+ // Various parts of the codebase still refer to Main.uiGroup
+ // instead of using the layoutManager. This keeps that code
+ // working until it's updated.
+ this.uiGroup = this.layoutManager.uiGroup;
+
+ this.padOsdService = new PadOsd.PadOsdService();
+ this.xdndHandler = new XdndHandler.XdndHandler();
+ this.ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
+ this.osdWindowManager = new OsdWindow.OsdWindowManager();
+ this.osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
+ this.overview = new Overview.Overview();
+ this.kbdA11yDialog = new KbdA11yDialog.KbdA11yDialog();
+ this.wm = new WindowManager.WindowManager();
+ this.magnifier = new Magnifier.Magnifier();
+ this.locatePointer = new LocatePointer.LocatePointer();
+
+ if (LoginManager.canLock())
+ this.screenShield = new ScreenShield.ScreenShield();
+
+ this.inputMethod = new InputMethod.InputMethod();
+ Clutter.get_default_backend().set_input_method(this.inputMethod);
+
+ this.messageTray = new MessageTray.MessageTray();
+ this.panel = new Panel.Panel();
+ this.keyboard = new Keyboard.KeyboardManager();
+ this.notificationDaemon = new NotificationDaemon.NotificationDaemon();
+ this.windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
+ this.componentManager = new Components.ComponentManager();
+
+ this.introspectService = new Introspect.IntrospectService();
+
+ this.layoutManager.init();
+ this.overview.init();
+
+ new PointerA11yTimeout.PointerA11yTimeout();
+
+ global.connect('locate-pointer', () => {
+ this.locatePointer.show();
+ });
+
+ global.display.connect('show-restart-message', (display, message) => {
+ showRestartMessage(message);
+ return true;
+ });
+
+ global.display.connect('restart', () => {
+ global.reexec_self();
+ return true;
+ });
+
+ global.display.connect('gl-video-memory-purged', this.loadTheme);
+
+ // Provide the bus object for gnome-session to
+ // initiate logouts.
+ EndSessionDialog.init();
+
+ // We're ready for the session manager to move to the next phase
+ GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
+ log('>>>>');
+ Shell.util_sd_notify();
+ global.context.notify_ready();
+ log('<<<<<')
+ return GLib.SOURCE_REMOVE;
+ });
+
+ this._startDate = new Date();
+
+ // ExtensionDownloader.init();
+ // this.extensionManager = new ExtensionSystem.ExtensionManager();
+ // this.extensionManager.init();
+
+ if (this.sessionMode.isGreeter && this.screenShield) {
+ this.layoutManager.connect('startup-prepared', () => {
+ log('Startup Prepared!');
+ this.screenShield.showDialog();
});
}
-
- let credentials = new Gio.Credentials();
- if (credentials.get_unix_user() === 0) {
- notify(_('Logged in as a privileged user'),
- _('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
- } else if (sessionMode.showWelcomeDialog) {
- _handleShowWelcomeScreen();
- }
-
- if (sessionMode.currentMode !== 'gdm' &&
- sessionMode.currentMode !== 'initial-setup')
- _handleLockScreenWarning();
-
- LoginManager.registerSessionWithGDM();
-
- let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
- if (perfModuleName) {
- let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
- let module = eval('imports.perf.%s;'.format(perfModuleName));
- Scripting.runPerfScript(module, perfOutput);
+
+ this.layoutManager.connect('startup-complete', () => {
+ log('Startup Complete!');
+ if (this.actionMode == Shell.ActionMode.NONE)
+ this.actionMode = Shell.ActionMode.NORMAL;
+
+ if (this.screenShield)
+ this.screenShield.lockIfWasLocked();
+
+ if (this.sessionMode.currentMode != 'gdm' &&
+ this.sessionMode.currentMode != 'initial-setup') {
+ GLib.log_structured(LOG_DOMAIN, GLib.LogLevelFlags.LEVEL_MESSAGE, {
+ 'MESSAGE': 'GNOME Shell started at %s'.format(this._startDate),
+ 'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID,
+ });
+ }
+
+ let credentials = new Gio.Credentials();
+ if (credentials.get_unix_user() === 0) {
+ this.notify(_('Logged in as a privileged user'),
+ _('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
+ } else if (this.sessionMode.showWelcomeDialog) {
+ this._handleShowWelcomeScreen();
+ }
+
+ if (this.sessionMode.currentMode !== 'gdm' &&
+ this.sessionMode.currentMode !== 'initial-setup')
+ this._handleLockScreenWarning();
+
+ LoginManager.registerSessionWithGDM();
+
+ let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
+ if (perfModuleName) {
+ let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
+ let module = eval('imports.perf.%s;'.format(perfModuleName));
+ Scripting.runPerfScript(module, perfOutput);
+ }
+ });
+
+ log('done init...');
+ }
+
+ _handleShowWelcomeScreen() {
+ const lastShownVersion = global.settings.get_string(WELCOME_DIALOG_LAST_SHOWN_VERSION);
+ if (Util.GNOMEversionCompare(WELCOME_DIALOG_LAST_TOUR_CHANGE, lastShownVersion) > 0) {
+ this.openWelcomeDialog();
+ global.settings.set_string(WELCOME_DIALOG_LAST_SHOWN_VERSION, Config.PACKAGE_VERSION);
}
- });
-}
-
-function _handleShowWelcomeScreen() {
- const lastShownVersion = global.settings.get_string(WELCOME_DIALOG_LAST_SHOWN_VERSION);
- if (Util.GNOMEversionCompare(WELCOME_DIALOG_LAST_TOUR_CHANGE, lastShownVersion) > 0) {
- openWelcomeDialog();
- global.settings.set_string(WELCOME_DIALOG_LAST_SHOWN_VERSION, Config.PACKAGE_VERSION);
}
-}
-async function _handleLockScreenWarning() {
- const path = '%s/lock-warning-shown'.format(global.userdatadir);
- const file = Gio.File.new_for_path(path);
-
- const hasLockScreen = screenShield !== null;
- if (hasLockScreen) {
- try {
- await file.delete_async(0, null);
- } catch (e) {
- if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+ async _handleLockScreenWarning() {
+ const path = '%s/lock-warning-shown'.format(global.userdatadir);
+ const file = Gio.File.new_for_path(path);
+
+ const hasLockScreen = this.screenShield !== null;
+ if (hasLockScreen) {
+ try {
+ await file.delete_async(0, null);
+ } catch (e) {
+ if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+ logError(e);
+ }
+ } else {
+ try {
+ if (!await file.touch_async())
+ return;
+ } catch (e) {
logError(e);
- }
- } else {
- try {
- if (!await file.touch_async())
- return;
- } catch (e) {
- logError(e);
- }
+ }
- notify(
- _('Screen Lock disabled'),
- _('Screen Locking requires the GNOME display manager.'));
+ this.notify(
+ _('Screen Lock disabled'),
+ _('Screen Locking requires the GNOME display manager.'));
+ }
}
-}
+ _getStylesheet(name) {
+ let stylesheet;
-function _getStylesheet(name) {
- let stylesheet;
+ stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/%s'.format(name));
+ if (stylesheet.query_exists(null))
+ return stylesheet;
- stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/%s'.format(name));
- if (stylesheet.query_exists(null))
- return stylesheet;
+ let dataDirs = GLib.get_system_data_dirs();
+ for (let i = 0; i < dataDirs.length; i++) {
+ let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'theme', name]);
+ stylesheet = Gio.file_new_for_path(path);
+ if (stylesheet.query_exists(null))
+ return stylesheet;
+ }
- let dataDirs = GLib.get_system_data_dirs();
- for (let i = 0; i < dataDirs.length; i++) {
- let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'theme', name]);
- stylesheet = Gio.file_new_for_path(path);
+ stylesheet = Gio.File.new_for_path('%s/theme/%s'.format(global.datadir, name));
if (stylesheet.query_exists(null))
return stylesheet;
- }
- stylesheet = Gio.File.new_for_path('%s/theme/%s'.format(global.datadir, name));
- if (stylesheet.query_exists(null))
- return stylesheet;
+ return null;
+ }
- return null;
-}
+ _getDefaultStylesheet() {
+ let stylesheet = null;
+ let name = this.sessionMode.stylesheetName;
-function _getDefaultStylesheet() {
- let stylesheet = null;
- let name = sessionMode.stylesheetName;
+ // Look for a high-contrast variant first when using GTK+'s HighContrast
+ // theme
+ if (St.Settings.get().gtk_theme == 'HighContrast')
+ stylesheet = this._getStylesheet(name.replace('.css', '-high-contrast.css'));
- // Look for a high-contrast variant first when using GTK+'s HighContrast
- // theme
- if (St.Settings.get().gtk_theme == 'HighContrast')
- stylesheet = _getStylesheet(name.replace('.css', '-high-contrast.css'));
+ if (stylesheet == null)
+ stylesheet = this._getStylesheet(this.sessionMode.stylesheetName);
- if (stylesheet == null)
- stylesheet = _getStylesheet(sessionMode.stylesheetName);
+ return stylesheet;
+ }
- return stylesheet;
-}
+ _loadDefaultStylesheet() {
+ let stylesheet = this._getDefaultStylesheet();
+ if (this._defaultCssStylesheet && this._defaultCssStylesheet.equal(stylesheet))
+ return;
-function _loadDefaultStylesheet() {
- let stylesheet = _getDefaultStylesheet();
- if (_defaultCssStylesheet && _defaultCssStylesheet.equal(stylesheet))
- return;
+ this._defaultCssStylesheet = stylesheet;
+ this.loadTheme();
+ }
- _defaultCssStylesheet = stylesheet;
- loadTheme();
-}
+ /**
+ * getThemeStylesheet:
+ *
+ * Get the theme CSS file that the shell will load
+ *
+ * @returns {?Gio.File}: A #GFile that contains the theme CSS,
+ * null if using the default
+ */
+ getThemeStylesheet() {
+ return this._cssStylesheet;
+ }
-/**
- * getThemeStylesheet:
- *
- * Get the theme CSS file that the shell will load
- *
- * @returns {?Gio.File}: A #GFile that contains the theme CSS,
- * null if using the default
- */
-function getThemeStylesheet() {
- return _cssStylesheet;
-}
-/**
- * setThemeStylesheet:
+ /**
+ * setThemeStylesheet:
* @param {string=} cssStylesheet: A file path that contains the theme CSS,
* set it to null to use the default
*
* Set the theme CSS file that the shell will load
*/
-function setThemeStylesheet(cssStylesheet) {
- _cssStylesheet = cssStylesheet ? Gio.File.new_for_path(cssStylesheet) : null;
-}
+ setThemeStylesheet(cssStylesheet) {
+ this._cssStylesheet = cssStylesheet ? Gio.File.new_for_path(cssStylesheet) : null;
+ }
-function reloadThemeResource() {
- if (_themeResource)
- _themeResource._unregister();
+ reloadThemeResource() {
+ if (this._themeResource)
+ this._themeResource._unregister();
- _themeResource = Gio.Resource.load('%s/%s'.format(global.datadir,
- sessionMode.themeResourceName));
- _themeResource._register();
-}
+ this._themeResource = Gio.Resource.load('%s/%s'.format(global.datadir,
+ this.sessionMode.themeResourceName));
+ this._themeResource._register();
+ }
-function _loadOskLayouts() {
- _oskResource = Gio.Resource.load('%s/gnome-shell-osk-layouts.gresource'.format(global.datadir));
- _oskResource._register();
-}
+ _loadOskLayouts() {
+ this._oskResource = Gio.Resource.load('%s/gnome-shell-osk-layouts.gresource'.format(global.datadir));
+ this._oskResource._register();
+ }
-/**
- * loadTheme:
- *
- * Reloads the theme CSS file
- */
-function loadTheme() {
- let themeContext = St.ThemeContext.get_for_stage(global.stage);
- let previousTheme = themeContext.get_theme();
- let theme = new St.Theme({
- application_stylesheet: _cssStylesheet,
- default_stylesheet: _defaultCssStylesheet,
- });
+ /**
+ * loadTheme:
+ *
+ * Reloads the theme CSS file
+ */
+ loadTheme() {
+ let themeContext = St.ThemeContext.get_for_stage(global.stage);
+ let previousTheme = themeContext.get_theme();
- if (theme.default_stylesheet == null)
- throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
+ let theme = new St.Theme({
+ application_stylesheet: this._cssStylesheet,
+ default_stylesheet: this._defaultCssStylesheet,
+ });
- if (previousTheme) {
- let customStylesheets = previousTheme.get_custom_stylesheets();
+ if (theme.default_stylesheet == null)
+ throw new Error("No valid stylesheet found for '%s'".format(this.sessionMode.stylesheetName));
- for (let i = 0; i < customStylesheets.length; i++)
- theme.load_stylesheet(customStylesheets[i]);
- }
+ if (previousTheme) {
+ let customStylesheets = previousTheme.get_custom_stylesheets();
- themeContext.set_theme(theme);
-}
+ for (let i = 0; i < customStylesheets.length; i++)
+ theme.load_stylesheet(customStylesheets[i]);
+ }
-/**
- * notify:
- * @param {string} msg: A message
- * @param {string} details: Additional information
- */
-function notify(msg, details) {
- let source = new MessageTray.SystemNotificationSource();
- messageTray.add(source);
- let notification = new MessageTray.Notification(source, msg, details);
- notification.setTransient(true);
- source.showNotification(notification);
-}
+ themeContext.set_theme(theme);
+ }
-/**
- * notifyError:
- * @param {string} msg: An error message
- * @param {string} details: Additional information
- *
- * See shell_global_notify_problem().
- */
-function notifyError(msg, details) {
- // Also print to stderr so it's logged somewhere
- if (details)
- log('error: %s: %s'.format(msg, details));
- else
- log('error: %s'.format(msg));
-
- notify(msg, details);
-}
+ /**
+ * notify:
+ * @param {string} msg: A message
+ * @param {string} details: Additional information
+ */
+ notify(msg, details) {
+ let source = new MessageTray.SystemNotificationSource();
+ this.messageTray.add(source);
+ let notification = new MessageTray.Notification(source, msg, details);
+ notification.setTransient(true);
+ source.showNotification(notification);
+ }
-function _findModal(actor) {
- for (let i = 0; i < modalActorFocusStack.length; i++) {
- if (modalActorFocusStack[i].actor == actor)
- return i;
+ /**
+ * notifyError:
+ * @param {string} msg: An error message
+ * @param {string} details: Additional information
+ *
+ * See shell_global_notify_problem().
+ */
+ notifyError(msg, details) {
+ // Also print to stderr so it's logged somewhere
+ if (details)
+ log('error: %s: %s'.format(msg, details));
+ else
+ log('error: %s'.format(msg));
+
+ this.notify(msg, details);
}
- return -1;
-}
-/**
- * pushModal:
- * @param {Clutter.Actor} actor: actor which will be given keyboard focus
- * @param {Object=} params: optional parameters
- *
- * Ensure we are in a mode where all keyboard and mouse input goes to
- * the stage, and focus @actor. Multiple calls to this function act in
- * a stacking fashion; the effect will be undone when an equal number
- * of popModal() invocations have been made.
- *
- * Next, record the current Clutter keyboard focus on a stack. If the
- * modal stack returns to this actor, reset the focus to the actor
- * which was focused at the time pushModal() was invoked.
- *
- * @params may be used to provide the following parameters:
- * - timestamp: used to associate the call with a specific user initiated
- * event. If not provided then the value of
- * global.get_current_time() is assumed.
- *
- * - options: Meta.ModalOptions flags to indicate that the pointer is
- * already grabbed
- *
- * - actionMode: used to set the current Shell.ActionMode to filter
- * global keybindings; the default of NONE will filter
- * out all keybindings
- *
- * @returns {bool}: true iff we successfully acquired a grab or already had one
- */
-function pushModal(actor, params = {}) {
- const {
- timestamp = global.get_current_time(),
- options = 0,
- actionMode: modalActionMode = Shell.ActionMode.NONE,
- } = params;
-
- if (modalCount == 0) {
- if (!global.begin_modal(timestamp, options)) {
- log('pushModal: invocation of begin_modal failed');
- return false;
+ _findModal(actor) {
+ for (let i = 0; i < this.modalActorFocusStack.length; i++) {
+ if (this.modalActorFocusStack[i].actor == actor)
+ return i;
}
- Meta.disable_unredirect_for_display(global.display);
+ return -1;
}
- modalCount += 1;
- let actorDestroyId = actor.connect('destroy', () => {
- let index = _findModal(actor);
- if (index >= 0)
- popModal(actor);
- });
+ /**
+ * pushModal:
+ * @param {Clutter.Actor} actor: actor which will be given keyboard focus
+ * @param {Object=} params: optional parameters
+ *
+ * Ensure we are in a mode where all keyboard and mouse input goes to
+ * the stage, and focus @actor. Multiple calls to this function act in
+ * a stacking fashion; the effect will be undone when an equal number
+ * of popModal() invocations have been made.
+ *
+ * Next, record the current Clutter keyboard focus on a stack. If the
+ * modal stack returns to this actor, reset the focus to the actor
+ * which was focused at the time pushModal() was invoked.
+ *
+ * @params may be used to provide the following parameters:
+ * - timestamp: used to associate the call with a specific user initiated
+ * event. If not provided then the value of
+ * global.get_current_time() is assumed.
+ *
+ * - options: Meta.ModalOptions flags to indicate that the pointer is
+ * already grabbed
+ *
+ * - actionMode: used to set the current Shell.ActionMode to filter
+ * global keybindings; the default of NONE will filter
+ * out all keybindings
+ *
+ * @returns {boolean}: true iff we successfully acquired a grab or already had one
+ */
+ pushModal(actor, params) {
+ params = Params.parse(params, {
+ timestamp: global.get_current_time(),
+ options: 0,
+ actionMode: Shell.ActionMode.NONE
+ });
- let prevFocus = global.stage.get_key_focus();
- let prevFocusDestroyId;
- if (prevFocus != null) {
- prevFocusDestroyId = prevFocus.connect('destroy', () => {
- const index = modalActorFocusStack.findIndex(
- record => record.prevFocus === prevFocus);
+ if (this.modalCount == 0) {
+ if (!global.begin_modal(params.timestamp, params.options)) {
+ log('pushModal: invocation of begin_modal failed');
+ return false;
+ }
+ Meta.disable_unredirect_for_display(global.display);
+ }
+ this.modalCount += 1;
+ let actorDestroyId = actor.connect('destroy', () => {
+ let index = this._findModal(actor);
if (index >= 0)
- modalActorFocusStack[index].prevFocus = null;
+ this.popModal(actor);
});
- }
- modalActorFocusStack.push({ actor,
- destroyId: actorDestroyId,
- prevFocus,
- prevFocusDestroyId,
- actionMode });
-
- actionMode = modalActionMode;
- global.stage.set_key_focus(actor);
- return true;
-}
-/**
- * popModal:
- * @param {Clutter.Actor} actor: the actor passed to original invocation
- * of pushModal()
- * @param {number=} timestamp: optional timestamp
- *
- * Reverse the effect of pushModal(). If this invocation is undoing
- * the topmost invocation, then the focus will be restored to the
- * previous focus at the time when pushModal() was invoked.
- *
- * @timestamp is optionally used to associate the call with a specific user
- * initiated event. If not provided then the value of
- * global.get_current_time() is assumed.
- */
-function popModal(actor, timestamp) {
- if (timestamp == undefined)
- timestamp = global.get_current_time();
+ let prevFocus = global.stage.get_key_focus();
+ let prevFocusDestroyId;
+ if (prevFocus != null) {
+ prevFocusDestroyId = prevFocus.connect('destroy', () => {
+ const index = this.modalActorFocusStack.findIndex(
+ record => record.prevFocus === prevFocus);
- let focusIndex = _findModal(actor);
- if (focusIndex < 0) {
- global.stage.set_key_focus(null);
- global.end_modal(timestamp);
- actionMode = Shell.ActionMode.NORMAL;
+ if (index >= 0)
+ this.modalActorFocusStack[index].prevFocus = null;
+ });
+ }
+ this.modalActorFocusStack.push({
+ actor,
+ destroyId: actorDestroyId,
+ prevFocus,
+ prevFocusDestroyId,
+ actionMode: this.actionMode
+ });
- throw new Error('incorrect pop');
+ this.actionMode = params.actionMode;
+ global.stage.set_key_focus(actor);
+ return true;
}
- modalCount -= 1;
-
- let record = modalActorFocusStack[focusIndex];
- record.actor.disconnect(record.destroyId);
-
- if (focusIndex == modalActorFocusStack.length - 1) {
- if (record.prevFocus)
- record.prevFocus.disconnect(record.prevFocusDestroyId);
- actionMode = record.actionMode;
- global.stage.set_key_focus(record.prevFocus);
- } else {
- // If we have:
- // global.stage.set_focus(a);
- // Main.pushModal(b);
- // Main.pushModal(c);
- // Main.pushModal(d);
- //
- // then we have the stack:
- // [{ prevFocus: a, actor: b },
- // { prevFocus: b, actor: c },
- // { prevFocus: c, actor: d }]
- //
- // When actor c is destroyed/popped, if we only simply remove the
- // record, then the focus stack will be [a, c], rather than the correct
- // [a, b]. Shift the focus stack up before removing the record to ensure
- // that we get the correct result.
- let t = modalActorFocusStack[modalActorFocusStack.length - 1];
- if (t.prevFocus)
- t.prevFocus.disconnect(t.prevFocusDestroyId);
- // Remove from the middle, shift the focus chain up
- for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
- modalActorFocusStack[i].prevFocus = modalActorFocusStack[i - 1].prevFocus;
- modalActorFocusStack[i].prevFocusDestroyId = modalActorFocusStack[i - 1].prevFocusDestroyId;
- modalActorFocusStack[i].actionMode = modalActorFocusStack[i - 1].actionMode;
+ /**
+ * popModal:
+ * @param {Clutter.Actor} actor: the actor passed to original invocation
+ * of pushModal()
+ * @param {number=} timestamp: optional timestamp
+ *
+ * Reverse the effect of pushModal(). If this invocation is undoing
+ * the topmost invocation, then the focus will be restored to the
+ * previous focus at the time when pushModal() was invoked.
+ *
+ * @timestamp is optionally used to associate the call with a specific user
+ * initiated event. If not provided then the value of
+ * global.get_current_time() is assumed.
+ */
+ popModal(actor, timestamp) {
+ if (timestamp == undefined)
+ timestamp = global.get_current_time();
+
+ let focusIndex = this._findModal(actor);
+ if (focusIndex < 0) {
+ global.stage.set_key_focus(null);
+ global.end_modal(timestamp);
+ this.actionMode = Shell.ActionMode.NORMAL;
+
+ throw new Error('incorrect pop');
}
- }
- modalActorFocusStack.splice(focusIndex, 1);
- if (modalCount > 0)
- return;
+ this.modalCount -= 1;
+
+ let record = this.modalActorFocusStack[focusIndex];
+ record.actor.disconnect(record.destroyId);
+
+ const { modalActorFocusStack } = this;
+
+ if (focusIndex == this.modalActorFocusStack.length - 1) {
+ if (record.prevFocus)
+ record.prevFocus.disconnect(record.prevFocusDestroyId);
+ this.actionMode = record.actionMode;
+ global.stage.set_key_focus(record.prevFocus);
+ } else {
+ // If we have:
+ // global.stage.set_focus(a);
+ // Main.pushModal(b);
+ // Main.pushModal(c);
+ // Main.pushModal(d);
+ //
+ // then we have the stack:
+ // [{ prevFocus: a, actor: b },
+ // { prevFocus: b, actor: c },
+ // { prevFocus: c, actor: d }]
+ //
+ // When actor c is destroyed/popped, if we only simply remove the
+ // record, then the focus stack will be [a, c], rather than the correct
+ // [a, b]. Shift the focus stack up before removing the record to ensure
+ // that we get the correct result.
+
+ let t = modalActorFocusStack[modalActorFocusStack.length - 1];
+ if (t.prevFocus)
+ t.prevFocus.disconnect(t.prevFocusDestroyId);
+ // Remove from the middle, shift the focus chain up
+ for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
+ modalActorFocusStack[i].prevFocus = modalActorFocusStack[i - 1].prevFocus;
+ modalActorFocusStack[i].prevFocusDestroyId = modalActorFocusStack[i - 1].prevFocusDestroyId;
+ modalActorFocusStack[i].actionMode = modalActorFocusStack[i - 1].actionMode;
+ }
+ }
+ modalActorFocusStack.splice(focusIndex, 1);
- layoutManager.modalEnded();
- global.end_modal(timestamp);
- Meta.enable_unredirect_for_display(global.display);
- actionMode = Shell.ActionMode.NORMAL;
-}
+ if (this.modalCount > 0)
+ return;
-function createLookingGlass() {
- if (lookingGlass == null)
- lookingGlass = new LookingGlass.LookingGlass();
+ this.layoutManager.modalEnded();
+ global.end_modal(timestamp);
+ Meta.enable_unredirect_for_display(global.display);
+ this.actionMode = Shell.ActionMode.NORMAL;
+ }
- return lookingGlass;
-}
+ createLookingGlass() {
+ if (this.lookingGlass == null)
+ this.lookingGlass = new LookingGlass.LookingGlass();
-function openRunDialog() {
- if (runDialog == null)
- runDialog = new RunDialog.RunDialog();
+ return this.lookingGlass;
+ }
- runDialog.open();
-}
+ openRunDialog() {
+ if (this.runDialog == null)
+ this.runDialog = new RunDialog.RunDialog();
-function openWelcomeDialog() {
- if (welcomeDialog === null)
- welcomeDialog = new WelcomeDialog.WelcomeDialog();
+ this.runDialog.open();
+ }
- welcomeDialog.open();
-}
+ /**
+ * activateWindow:
+ * @param {Meta.Window} window: the window to activate
+ * @param {number=} time: current event time
+ * @param {number=} workspaceNum: window's workspace number
+ *
+ * Activates @window, switching to its workspace first if necessary,
+ * and switching out of the overview if it's currently active
+ */
+ activateWindow(window, time, workspaceNum) {
+ let workspaceManager = global.workspace_manager;
+ let activeWorkspaceNum = workspaceManager.get_active_workspace_index();
+ let windowWorkspaceNum = workspaceNum !== undefined ? workspaceNum : window.get_workspace().index();
+
+ if (!time)
+ time = global.get_current_time();
+
+ if (windowWorkspaceNum != activeWorkspaceNum) {
+ let workspace = workspaceManager.get_workspace_by_index(windowWorkspaceNum);
+ workspace.activate_with_focus(window, time);
+ } else {
+ window.activate(time);
+ }
-/**
- * activateWindow:
- * @param {Meta.Window} window: the window to activate
- * @param {number=} time: current event time
- * @param {number=} workspaceNum: window's workspace number
- *
- * Activates @window, switching to its workspace first if necessary,
- * and switching out of the overview if it's currently active
- */
-function activateWindow(window, time, workspaceNum) {
- let workspaceManager = global.workspace_manager;
- let activeWorkspaceNum = workspaceManager.get_active_workspace_index();
- let windowWorkspaceNum = workspaceNum !== undefined ? workspaceNum : window.get_workspace().index();
-
- if (!time)
- time = global.get_current_time();
-
- if (windowWorkspaceNum != activeWorkspaceNum) {
- let workspace = workspaceManager.get_workspace_by_index(windowWorkspaceNum);
- workspace.activate_with_focus(window, time);
- } else {
- window.activate(time);
+ this.overview.hide();
+ this.panel.closeCalendar();
}
- overview.hide();
- panel.closeCalendar();
-}
+ _deferredWorkData = {};
-// TODO - replace this timeout with some system to guess when the user might
-// be e.g. just reading the screen and not likely to interact.
-var DEFERRED_TIMEOUT_SECONDS = 20;
-var _deferredWorkData = {};
-// Work scheduled for some point in the future
-var _deferredWorkQueue = [];
-// Work we need to process before the next redraw
-var _beforeRedrawQueue = [];
-// Counter to assign work ids
-var _deferredWorkSequence = 0;
-var _deferredTimeoutId = 0;
-
-function _runDeferredWork(workId) {
- if (!_deferredWorkData[workId])
- return;
- let index = _deferredWorkQueue.indexOf(workId);
- if (index < 0)
- return;
-
- _deferredWorkQueue.splice(index, 1);
- _deferredWorkData[workId].callback();
- if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
- GLib.source_remove(_deferredTimeoutId);
- _deferredTimeoutId = 0;
+ // Work scheduled for some point in the future
+ _deferredWorkQueue = [];
+ // Work we need to process before the next redraw
+ _beforeRedrawQueue = [];
+ // Counter to assign work ids
+ _deferredWorkSequence = 0;
+ _deferredTimeoutId = 0;
+
+ _runDeferredWork(workId) {
+ if (!this._deferredWorkData[workId])
+ return;
+ let index = this._deferredWorkQueue.indexOf(workId);
+ if (index < 0)
+ return;
+
+ this._deferredWorkQueue.splice(index, 1);
+ this._deferredWorkData[workId].callback();
+ if (this._deferredWorkQueue.length == 0 && this._deferredTimeoutId > 0) {
+ GLib.source_remove(this._deferredTimeoutId);
+ this._deferredTimeoutId = 0;
+ }
}
-}
-function _runAllDeferredWork() {
- while (_deferredWorkQueue.length > 0)
- _runDeferredWork(_deferredWorkQueue[0]);
-}
+ _runAllDeferredWork() {
+ while (this._deferredWorkQueue.length > 0)
+ this._runDeferredWork(this._deferredWorkQueue[0]);
+ }
-function _runBeforeRedrawQueue() {
- for (let i = 0; i < _beforeRedrawQueue.length; i++) {
- let workId = _beforeRedrawQueue[i];
- _runDeferredWork(workId);
+ _runBeforeRedrawQueue() {
+ for (let i = 0; i < this._beforeRedrawQueue.length; i++) {
+ let workId = this._beforeRedrawQueue[i];
+ this._runDeferredWork(workId);
+ }
+ this._beforeRedrawQueue = [];
+ }
+
+ _queueBeforeRedraw(workId) {
+ this._beforeRedrawQueue.push(workId);
+ if (this._beforeRedrawQueue.length == 1) {
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
+ this._runBeforeRedrawQueue();
+ return false;
+ });
+ }
}
- _beforeRedrawQueue = [];
-}
-function _queueBeforeRedraw(workId) {
- _beforeRedrawQueue.push(workId);
- if (_beforeRedrawQueue.length == 1) {
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
- _runBeforeRedrawQueue();
- return false;
+ /**
+ * initializeDeferredWork:
+ * @param {Clutter.Actor} actor: an actor
+ * @param {(...args: any[]) => any} callback: Function to invoke to perform work
+ *
+ * This function sets up a callback to be invoked when either the
+ * given actor is mapped, or after some period of time when the machine
+ * is idle. This is useful if your actor isn't always visible on the
+ * screen (for example, all actors in the overview), and you don't want
+ * to consume resources updating if the actor isn't actually going to be
+ * displaying to the user.
+ *
+ * Note that queueDeferredWork is called by default immediately on
+ * initialization as well, under the assumption that new actors
+ * will need it.
+ *
+ * @returns {string}: A string work identifier
+ */
+ initializeDeferredWork(actor, callback) {
+ // Turn into a string so we can use as an object property
+ let workId = (++this._deferredWorkSequence).toString();
+ this._deferredWorkData[workId] = {
+ actor,
+ callback
+ };
+ actor.connect('notify::mapped', () => {
+ if (!(actor.mapped && this._deferredWorkQueue.includes(workId)))
+ return;
+ this._queueBeforeRedraw(workId);
});
+ actor.connect('destroy', () => {
+ let index = this._deferredWorkQueue.indexOf(workId);
+ if (index >= 0)
+ this._deferredWorkQueue.splice(index, 1);
+ delete this._deferredWorkData[workId];
+ });
+ this.queueDeferredWork(workId);
+ return workId;
}
-}
-/**
- * initializeDeferredWork:
- * @param {Clutter.Actor} actor: an actor
- * @param {callback} callback: Function to invoke to perform work
- *
- * This function sets up a callback to be invoked when either the
- * given actor is mapped, or after some period of time when the machine
- * is idle. This is useful if your actor isn't always visible on the
- * screen (for example, all actors in the overview), and you don't want
- * to consume resources updating if the actor isn't actually going to be
- * displaying to the user.
- *
- * Note that queueDeferredWork is called by default immediately on
- * initialization as well, under the assumption that new actors
- * will need it.
- *
- * @returns {string}: A string work identifier
- */
-function initializeDeferredWork(actor, callback) {
- // Turn into a string so we can use as an object property
- let workId = (++_deferredWorkSequence).toString();
- _deferredWorkData[workId] = { actor,
- callback };
- actor.connect('notify::mapped', () => {
- if (!(actor.mapped && _deferredWorkQueue.includes(workId)))
+ /**
+ * queueDeferredWork:
+ * @param {string} workId: work identifier
+ *
+ * Ensure that the work identified by @workId will be
+ * run on map or timeout. You should call this function
+ * for example when data being displayed by the actor has
+ * changed.
+ */
+ queueDeferredWork(workId) {
+ let data = this._deferredWorkData[workId];
+ if (!data) {
+ let message = 'Invalid work id %s'.format(workId);
+ logError(new Error(message), message);
return;
- _queueBeforeRedraw(workId);
- });
- actor.connect('destroy', () => {
- let index = _deferredWorkQueue.indexOf(workId);
- if (index >= 0)
- _deferredWorkQueue.splice(index, 1);
- delete _deferredWorkData[workId];
- });
- queueDeferredWork(workId);
- return workId;
-}
-
-/**
- * queueDeferredWork:
- * @param {string} workId: work identifier
- *
- * Ensure that the work identified by @workId will be
- * run on map or timeout. You should call this function
- * for example when data being displayed by the actor has
- * changed.
- */
-function queueDeferredWork(workId) {
- let data = _deferredWorkData[workId];
- if (!data) {
- let message = 'Invalid work id %d'.format(workId);
- logError(new Error(message), message);
- return;
+ }
+ if (!this._deferredWorkQueue.includes(workId))
+ this._deferredWorkQueue.push(workId);
+ if (data.actor.mapped) {
+ this._queueBeforeRedraw(workId);
+ } else if (this._deferredTimeoutId == 0) {
+ this._deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => {
+ this._runAllDeferredWork();
+ this._deferredTimeoutId = 0;
+ return GLib.SOURCE_REMOVE;
+ });
+ GLib.Source.set_name_by_id(this._deferredTimeoutId, '[gnome-shell] _runAllDeferredWork');
+ }
}
- if (!_deferredWorkQueue.includes(workId))
- _deferredWorkQueue.push(workId);
- if (data.actor.mapped) {
- _queueBeforeRedraw(workId);
- } else if (_deferredTimeoutId == 0) {
- _deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => {
- _runAllDeferredWork();
- _deferredTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- });
- GLib.Source.set_name_by_id(_deferredTimeoutId, '[gnome-shell] _runAllDeferredWork');
+
+ openWelcomeDialog() {
+ if (this.welcomeDialog === null)
+ this.welcomeDialog = new WelcomeDialog.WelcomeDialog();
+
+ this.welcomeDialog.open();
}
+};
+
+export const main = new Main();
+
+ExtensionUtils._setMain(main);
+
+globalThis.getMain = function getMain() {
+ return main;
}
-var RestartMessage = GObject.registerClass(
-class RestartMessage extends ModalDialog.ModalDialog {
- _init(message) {
- super._init({ shellReactive: true,
- styleClass: 'restart-message headline',
- shouldFadeIn: false,
- destroyOnClose: true });
-
- let label = new St.Label({
- text: message,
- x_align: Clutter.ActorAlign.CENTER,
- y_align: Clutter.ActorAlign.CENTER,
- });
+export default main;
- this.contentLayout.add_child(label);
- this.buttonLayout.hide();
- }
-});
+Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
+Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
+
+// TODO - replace this timeout with some system to guess when the user might
+// be e.g. just reading the screen and not likely to interact.
+export const DEFERRED_TIMEOUT_SECONDS = 20;
+
+export const RestartMessage = GObject.registerClass(
+ class RestartMessage extends ModalDialog.ModalDialog {
+ _init(message) {
+ super._init({
+ shellReactive: true,
+ styleClass: 'restart-message headline',
+ shouldFadeIn: false,
+ destroyOnClose: true
+ });
+
+ let label = new St.Label({
+ text: message,
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.CENTER,
+ });
+
+ this.contentLayout.add_child(label);
+ this.buttonLayout.hide();
+ }
+ });
function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);
restartMessage.open();
}
-var AnimationsSettings = class {
+export class AnimationsSettings {
constructor() {
let backend = global.backend;
if (!backend.is_rendering_hardware_accelerated()) {
diff --git a/js/ui/messageList.js b/js/ui/messageList.js
index c68ab77fd..879fa3716 100644
--- a/js/ui/messageList.js
+++ b/js/ui/messageList.js
@@ -1,14 +1,22 @@
/* exported MessageListSection */
-const { Atk, Clutter, Gio, GLib,
- GObject, Graphene, Meta, Pango, St } = imports.gi;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Graphene from 'gi://Graphene';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import St from 'gi://St';
-const Util = imports.misc.util;
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
-var MESSAGE_ANIMATION_TIME = 100;
+import * as Util from '../misc/util.js';
-var DEFAULT_EXPAND_LINES = 6;
+export let MESSAGE_ANIMATION_TIME = 100;
+
+export let DEFAULT_EXPAND_LINES = 6;
function _fixMarkup(text, allowMarkup) {
if (allowMarkup) {
@@ -31,7 +39,7 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1);
}
-var URLHighlighter = GObject.registerClass(
+export const URLHighlighter = GObject.registerClass(
class URLHighlighter extends St.Label {
_init(text = '', lineWrap, allowMarkup) {
super._init({
@@ -159,7 +167,7 @@ class URLHighlighter extends St.Label {
}
});
-var ScaleLayout = GObject.registerClass(
+export const ScaleLayout = GObject.registerClass(
class ScaleLayout extends Clutter.BinLayout {
_init(params) {
this._container = null;
@@ -188,6 +196,9 @@ class ScaleLayout extends Clutter.BinLayout {
}
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
this._connectContainer(container);
@@ -196,6 +207,9 @@ class ScaleLayout extends Clutter.BinLayout {
Math.floor(nat * container.scale_x)];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(container, forWidth) {
this._connectContainer(container);
@@ -205,7 +219,7 @@ class ScaleLayout extends Clutter.BinLayout {
}
});
-var LabelExpanderLayout = GObject.registerClass({
+export const LabelExpanderLayout = GObject.registerClass({
Properties: {
'expansion': GObject.ParamSpec.double('expansion',
'Expansion',
@@ -215,6 +229,9 @@ var LabelExpanderLayout = GObject.registerClass({
0, 1, 0),
},
}, class LabelExpanderLayout extends Clutter.LayoutManager {
+ /**
+ * @param {*} params
+ */
_init(params) {
this._expansion = 0;
this._expandLines = DEFAULT_EXPAND_LINES;
@@ -251,6 +268,9 @@ var LabelExpanderLayout = GObject.registerClass({
this._container = container;
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
let [min, nat] = [0, 0];
@@ -266,6 +286,9 @@ var LabelExpanderLayout = GObject.registerClass({
return [min, nat];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(container, forWidth) {
let [min, nat] = [0, 0];
@@ -295,13 +318,17 @@ var LabelExpanderLayout = GObject.registerClass({
});
-var Message = GObject.registerClass({
+export const Message = GObject.registerClass({
Signals: {
'close': {},
'expanded': {},
'unexpanded': {},
},
}, class Message extends St.Button {
+ /**
+ * @param {*} title
+ * @param {*} body
+ */
_init(title, body) {
super._init({
style_class: 'message',
@@ -313,6 +340,7 @@ var Message = GObject.registerClass({
this.expanded = false;
this._useBodyMarkup = false;
+ this.notification = null;
let vbox = new St.BoxLayout({
vertical: true,
@@ -361,11 +389,11 @@ var Message = GObject.registerClass({
});
titleBox.add_actor(this._closeButton);
- this._bodyStack = new St.Widget({ x_expand: true });
- this._bodyStack.layout_manager = new LabelExpanderLayout();
+ this._bodyStack = new St.Widget({ x_expand: true, layout_manager: new LabelExpanderLayout() });
+
contentBox.add_actor(this._bodyStack);
- this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup);
+ this.bodyLabel = new URLHighlighter({ text: '', lineWrap: false, allowMarkup: this._useBodyMarkup });
this.bodyLabel.add_style_class_name('message-body');
this._bodyStack.add_actor(this.bodyLabel);
this.setBody(body);
@@ -532,7 +560,7 @@ var Message = GObject.registerClass({
}
});
-var MessageListSection = GObject.registerClass({
+export const MessageListSection = GObject.registerClass({
Properties: {
'can-clear': GObject.ParamSpec.boolean(
'can-clear', 'can-clear', 'can-clear',
@@ -557,6 +585,7 @@ var MessageListSection = GObject.registerClass({
x_expand: true,
});
+ /** @type {St.BoxLayout<St.Bin<Message["prototype"]>>} */
this._list = new St.BoxLayout({ style_class: 'message-list-section-list',
vertical: true });
this.add_actor(this._list);
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 7596f105f..fb32e52ca 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -3,32 +3,38 @@
NotificationApplicationPolicy, Source, SourceActor,
SystemNotificationSource, MessageTray */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const Calendar = imports.ui.calendar;
-const GnomeSession = imports.misc.gnomeSession;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Calendar from './calendar.js';
+import * as GnomeSession from '../misc/gnomeSession.js';
+import * as Layout from './layout.js';
+import Main from './main.js';
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
-var ANIMATION_TIME = 200;
-var NOTIFICATION_TIMEOUT = 4000;
+export let ANIMATION_TIME = 200;
+export let NOTIFICATION_TIMEOUT = 4000;
-var HIDE_TIMEOUT = 200;
-var LONGER_HIDE_TIMEOUT = 600;
+export let HIDE_TIMEOUT = 200;
+export let LONGER_HIDE_TIMEOUT = 600;
-var MAX_NOTIFICATIONS_IN_QUEUE = 3;
-var MAX_NOTIFICATIONS_PER_SOURCE = 3;
-var MAX_NOTIFICATION_BUTTONS = 3;
+export let MAX_NOTIFICATIONS_IN_QUEUE = 3;
+export let MAX_NOTIFICATIONS_PER_SOURCE = 3;
+export let MAX_NOTIFICATION_BUTTONS = 3;
// We delay hiding of the tray if the mouse is within MOUSE_LEFT_ACTOR_THRESHOLD
// range from the point where it left the tray.
-var MOUSE_LEFT_ACTOR_THRESHOLD = 20;
+export let MOUSE_LEFT_ACTOR_THRESHOLD = 20;
-var IDLE_TIME = 1000;
+export let IDLE_TIME = 1000;
-var State = {
+export const State = {
HIDDEN: 0,
SHOWING: 1,
SHOWN: 2,
@@ -42,7 +48,8 @@ var State = {
// notifications that were requested to be destroyed by the associated source,
// and REPLACED for notifications that were destroyed as a consequence of a
// newer version having replaced them.
-var NotificationDestroyedReason = {
+/** @enum {number} */
+export const NotificationDestroyedReason = {
EXPIRED: 1,
DISMISSED: 2,
SOURCE_CLOSED: 3,
@@ -53,7 +60,8 @@ var NotificationDestroyedReason = {
// urgency values map to the corresponding values for the notifications received
// through the notification daemon. HIGH urgency value is used for chats received
// through the Telepathy client.
-var Urgency = {
+/** @enum {number} */
+export const Urgency = {
LOW: 0,
NORMAL: 1,
HIGH: 2,
@@ -66,12 +74,13 @@ var Urgency = {
// contain information private to the physical system (for example, battery
// status) and hence the same for every user. This affects whether the content
// of a notification is shown on the lock screen.
-var PrivacyScope = {
+/** @enum {number} */
+export const PrivacyScope = {
USER: 0,
SYSTEM: 1,
};
-var FocusGrabber = class FocusGrabber {
+export class FocusGrabber {
constructor(actor) {
this._actor = actor;
this._prevKeyFocusActor = null;
@@ -132,7 +141,7 @@ var FocusGrabber = class FocusGrabber {
// source, such as whether to play sound or honour the critical bit.
//
// A notification without a policy object will inherit the default one.
-var NotificationPolicy = GObject.registerClass({
+export const NotificationPolicy = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'enable': GObject.ParamSpec.boolean(
@@ -187,7 +196,7 @@ var NotificationPolicy = GObject.registerClass({
}
});
-var NotificationGenericPolicy = GObject.registerClass({
+export const NotificationGenericPolicy = GObject.registerClass({
}, class NotificationGenericPolicy extends NotificationPolicy {
_init() {
super._init();
@@ -204,6 +213,7 @@ var NotificationGenericPolicy = GObject.registerClass({
}
_changed(settings, key) {
+ // @ts-expect-error this.constructor cannot be statically analyzed.
if (this.constructor.find_property(key))
this.notify(key);
}
@@ -217,7 +227,7 @@ var NotificationGenericPolicy = GObject.registerClass({
}
});
-var NotificationApplicationPolicy = GObject.registerClass({
+export const NotificationApplicationPolicy = GObject.registerClass({
}, class NotificationApplicationPolicy extends NotificationPolicy {
_init(id) {
super._init();
@@ -253,6 +263,8 @@ var NotificationApplicationPolicy = GObject.registerClass({
}
_changed(settings, key) {
+ // FIXME
+ // @ts-expect-error
if (this.constructor.find_property(key))
this.notify(key);
}
@@ -345,7 +357,7 @@ var NotificationApplicationPolicy = GObject.registerClass({
// @source allows playing sounds).
//
// [1] https://developer.gnome.org/notification-spec/#markup
-var Notification = GObject.registerClass({
+export const Notification = GObject.registerClass({
Properties: {
'acknowledged': GObject.ParamSpec.boolean(
'acknowledged', 'acknowledged', 'acknowledged',
@@ -358,6 +370,12 @@ var Notification = GObject.registerClass({
'updated': { param_types: [GObject.TYPE_BOOLEAN] },
},
}, class Notification extends GObject.Object {
+ /**
+ * @param {*} source
+ * @param {*} title
+ * @param {*} banner
+ * @param {*} params
+ */
_init(source, title, banner, params) {
super._init();
@@ -376,6 +394,8 @@ var Notification = GObject.registerClass({
this.actions = [];
this.setResident(false);
+ this.answered = false;
+
// If called with only one argument we assume the caller
// will call .update() later on. This is the case of
// NotificationDaemon, which wants to use the same code
@@ -507,7 +527,7 @@ var Notification = GObject.registerClass({
}
});
-var NotificationBanner = GObject.registerClass({
+export const NotificationBanner = GObject.registerClass({
Signals: {
'done-displaying': {},
'unfocused': {},
@@ -606,7 +626,7 @@ var NotificationBanner = GObject.registerClass({
}
});
-var SourceActor = GObject.registerClass(
+export const SourceActor = GObject.registerClass(
class SourceActor extends St.Widget {
_init(source, size) {
super._init();
@@ -645,7 +665,13 @@ class SourceActor extends St.Widget {
}
});
-var Source = GObject.registerClass({
+/**
+ * @typedef {object} SourceParams
+ * @property {string} [title]
+ * @property {string} [iconName]
+ */
+
+export const Source = GObject.registerClass({
Properties: {
'count': GObject.ParamSpec.int(
'count', 'count', 'count',
@@ -707,6 +733,9 @@ var Source = GObject.registerClass({
this.notify('count');
}
+ /**
+ * @returns {NotificationPolicy["prototype"]}
+ */
_createPolicy() {
return new NotificationGenericPolicy();
}
@@ -737,6 +766,9 @@ var Source = GObject.registerClass({
icon_size: size });
}
+ /**
+ * @returns {Gio.Icon}
+ */
getIcon() {
return new Gio.ThemedIcon({ name: this.iconName });
}
@@ -808,7 +840,7 @@ var Source = GObject.registerClass({
}
});
-var MessageTray = GObject.registerClass({
+export const MessageTray = GObject.registerClass({
Signals: {
'queue-changed': {},
'source-added': { param_types: [Source.$gtype] },
@@ -822,7 +854,7 @@ var MessageTray = GObject.registerClass({
layout_manager: new Clutter.BinLayout(),
});
- this._presence = new GnomeSession.Presence((proxy, _error) => {
+ this._presence = GnomeSession.Presence((proxy, _error) => {
this._onStatusChanged(proxy.status);
});
this._busy = false;
@@ -1438,10 +1470,10 @@ var MessageTray = GObject.registerClass({
}
});
-var SystemNotificationSource = GObject.registerClass(
+export const SystemNotificationSource = GObject.registerClass(
class SystemNotificationSource extends Source {
_init() {
- super._init(_("System Information"), 'dialog-information-symbolic');
+ super._init({ title: _("System Information"), iconName: 'dialog-information-symbolic' });
}
open() {
diff --git a/js/ui/modalDialog.js b/js/ui/modalDialog.js
index 10fe90310..74b538373 100644
--- a/js/ui/modalDialog.js
+++ b/js/ui/modalDialog.js
@@ -1,17 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModalDialog */
-const { Atk, Clutter, GObject, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const Layout = imports.ui.layout;
-const Lightbox = imports.ui.lightbox;
-const Main = imports.ui.main;
-
-var OPEN_AND_CLOSE_TIME = 100;
-var FADE_OUT_DIALOG_TIME = 1000;
-
-var State = {
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Dialog from './dialog.js';
+import * as Layout from './layout.js';
+import * as Lightbox from './lightbox.js';
+import Main from './main.js';
+
+export let OPEN_AND_CLOSE_TIME = 100;
+export let FADE_OUT_DIALOG_TIME = 1000;
+
+/** @enum {number} */
+export const State = {
OPENED: 0,
CLOSED: 1,
OPENING: 2,
@@ -19,7 +24,17 @@ var State = {
FADED_OUT: 4,
};
-var ModalDialog = GObject.registerClass({
+/**
+ * @typedef {object} ModalDialogParams
+ * @property {boolean} shellReactive
+ * @property {string | null} styleClass
+ * @property {Shell.ActionMode} actionMode
+ * @property {boolean} shouldFadeIn
+ * @property {boolean} shouldFadeOut
+ * @property {boolean} destroyOnClose
+ */
+
+export const ModalDialog = GObject.registerClass({
Properties: {
'state': GObject.ParamSpec.int('state', 'Dialog state', 'state',
GObject.ParamFlags.READABLE,
@@ -29,7 +44,7 @@ var ModalDialog = GObject.registerClass({
},
Signals: { 'opened': {}, 'closed': {} },
}, class ModalDialog extends St.Widget {
- _init(params = {}) {
+ _init(params = {}, ...args) {
super._init({ visible: false,
x: 0,
y: 0,
@@ -258,7 +273,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => (this.state = State.FADED_OUT),
+ onComplete: () => (this._setState(State.FADED_OUT)),
});
}
});
diff --git a/js/ui/mpris.js b/js/ui/mpris.js
index 6038142c6..98e3b8c0a 100644
--- a/js/ui/mpris.js
+++ b/js/ui/mpris.js
@@ -1,11 +1,14 @@
/* exported MediaSection */
-const { Gio, GObject, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
-const Main = imports.ui.main;
-const MessageList = imports.ui.messageList;
+import Main from './main.js';
+import * as MessageList from './messageList.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const DBusIface = loadInterfaceXML('org.freedesktop.DBus');
const DBusProxy = Gio.DBusProxy.makeProxyWrapper(DBusIface);
@@ -18,8 +21,11 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
-var MediaMessage = GObject.registerClass(
+export const MediaMessage = GObject.registerClass(
class MediaMessage extends MessageList.Message {
+ /**
+ * @param {*} player
+ */
_init(player) {
super._init('', '');
@@ -93,7 +99,7 @@ class MediaMessage extends MessageList.Message {
}
});
-var MprisPlayer = class MprisPlayer extends Signals.EventEmitter {
+export class MprisPlayer extends Signals.EventEmitter {
constructor(busName) {
super();
@@ -243,7 +249,7 @@ var MprisPlayer = class MprisPlayer extends Signals.EventEmitter {
}
};
-var MediaSection = GObject.registerClass(
+export const MediaSection = GObject.registerClass(
class MediaSection extends MessageList.MessageListSection {
_init() {
super._init();
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index e75c2fdc0..e4de618da 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -1,30 +1,37 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
-const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
+import GdkPixbuf from 'gi://GdkPixbuf';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
const Config = imports.misc.config;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
-var NotificationClosedReason = {
+/** @enum {number} */
+export const NotificationClosedReason = {
EXPIRED: 1,
DISMISSED: 2,
APP_CLOSED: 3,
UNDEFINED: 4,
};
-var Urgency = {
+/** @enum {number} */
+export const Urgency = {
LOW: 0,
NORMAL: 1,
CRITICAL: 2,
};
-var FdoNotificationDaemon = class FdoNotificationDaemon {
+export class FdoNotificationDaemon {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FdoNotificationsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
@@ -187,7 +194,8 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
let sender = invocation.get_sender();
let pid = hints['sender-pid'];
- let source = this._getSource(appName, pid, ndata, sender, null);
+ // FIXME
+ let source = this._getSource(appName, pid, ndata, sender);
this._notifyForSource(source, ndata);
return invocation.return_value(GLib.Variant.new('(u)', [id]));
@@ -342,7 +350,15 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
};
-var FdoNotificationDaemonSource = GObject.registerClass(
+/**
+ * @typedef {object} FdoNotificationDaemonSourceParams
+ * @property {string} title
+ * @property {number} pid
+ * @property {string} sender
+ * @property {string} appId
+ */
+
+export const FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
_init(title, pid, sender, appId) {
this.pid = pid;
@@ -466,8 +482,12 @@ const PRIORITY_URGENCY_MAP = {
urgent: MessageTray.Urgency.CRITICAL,
};
-var GtkNotificationDaemonNotification = GObject.registerClass(
+export const GtkNotificationDaemonNotification = GObject.registerClass(
class GtkNotificationDaemonNotification extends MessageTray.Notification {
+ /**
+ * @param {*} source
+ * @param {*} notification
+ */
_init(source, notification) {
super._init(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
@@ -542,14 +562,19 @@ function objectPathFromAppId(appId) {
return '/' + appId.replace(/\./g, '/').replace(/-/g, '_');
}
-function getPlatformData() {
- let startupId = GLib.Variant.new('s', '_TIME%s'.format(global.get_current_time()));
+export function getPlatformData() {
+ let startupId = GLib.Variant.new('s', '_TIME%d'.format(global.get_current_time()));
return { "desktop-startup-id": startupId };
}
function InvalidAppError() {}
-var GtkNotificationDaemonAppSource = GObject.registerClass(
+/**
+ * @typedef {object} GtkNotificationDaemonAppSourceParams
+ * @property {string} appId
+ */
+
+export const GtkNotificationDaemonAppSource = GObject.registerClass(
class GtkNotificationDaemonAppSource extends MessageTray.Source {
_init(appId) {
let objectPath = objectPathFromAppId(appId);
@@ -651,7 +676,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
-var GtkNotificationDaemon = class GtkNotificationDaemon {
+export class GtkNotificationDaemon {
constructor() {
this._sources = {};
@@ -756,7 +781,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
}
};
-var NotificationDaemon = class NotificationDaemon {
+export class NotificationDaemon {
constructor() {
this._fdoNotificationDaemon = new FdoNotificationDaemon();
this._gtkNotificationDaemon = new GtkNotificationDaemon();
diff --git a/js/ui/osdMonitorLabeler.js b/js/ui/osdMonitorLabeler.js
index b242ecca1..80099440c 100644
--- a/js/ui/osdMonitorLabeler.js
+++ b/js/ui/osdMonitorLabeler.js
@@ -1,11 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdMonitorLabeler */
-const { Clutter, Gio, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const Main = imports.ui.main;
-var OsdMonitorLabel = GObject.registerClass(
+import Main from './main.js';
+
+export const OsdMonitorLabel = GObject.registerClass(
class OsdMonitorLabel extends St.Widget {
_init(monitor, label) {
super._init({ x_expand: true, y_expand: true });
@@ -42,7 +47,7 @@ class OsdMonitorLabel extends St.Widget {
}
});
-var OsdMonitorLabeler = class {
+export class OsdMonitorLabeler {
constructor() {
this._monitorManager = Meta.MonitorManager.get();
this._client = null;
diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js
index bae4b862a..8f98c549b 100644
--- a/js/ui/osdWindow.js
+++ b/js/ui/osdWindow.js
@@ -1,17 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdWindowManager */
-const { Clutter, GLib, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const BarLevel = imports.ui.barLevel;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
+import * as BarLevel from './barLevel.js';
+import * as Layout from './layout.js';
+import Main from './main.js';
-var HIDE_TIMEOUT = 1500;
-var FADE_TIME = 100;
-var LEVEL_ANIMATION_TIME = 100;
+export let HIDE_TIMEOUT = 1500;
+export let FADE_TIME = 100;
+export let LEVEL_ANIMATION_TIME = 100;
-var OsdWindowConstraint = GObject.registerClass(
+export const OsdWindowConstraint = GObject.registerClass(
class OsdWindowConstraint extends Clutter.Constraint {
_init(props) {
this._minSize = 0;
@@ -41,7 +45,7 @@ class OsdWindowConstraint extends Clutter.Constraint {
}
});
-var OsdWindow = GObject.registerClass(
+export const OsdWindow = GObject.registerClass(
class OsdWindow extends St.Widget {
_init(monitorIndex) {
super._init({
@@ -199,7 +203,7 @@ class OsdWindow extends St.Widget {
}
});
-var OsdWindowManager = class {
+export class OsdWindowManager {
constructor() {
this._osdWindows = [];
Main.layoutManager.connect('monitors-changed',
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 176931c61..31d8f82e2 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -1,27 +1,33 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
// Time for initial animation going into Overview mode;
// this is defined here to make it available in imports.
-var ANIMATION_TIME = 250;
+export let ANIMATION_TIME = 250;
-const DND = imports.ui.dnd;
-const LayoutManager = imports.ui.layout;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const OverviewControls = imports.ui.overviewControls;
-const SwipeTracker = imports.ui.swipeTracker;
-const WindowManager = imports.ui.windowManager;
-const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
+import * as DND from './dnd.js';
+import * as LayoutManager from './layout.js';
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
+import * as OverviewControls from './overviewControls.js';
+import * as SwipeTracker from './swipeTracker.js';
+import * as WindowManager from './windowManager.js';
+import * as WorkspaceThumbnail from './workspaceThumbnail.js';
-var DND_WINDOW_SWITCH_TIMEOUT = 750;
+export let DND_WINDOW_SWITCH_TIMEOUT = 750;
-var OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
+export let OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
-var ShellInfo = class {
+export class ShellInfo {
constructor() {
this._source = null;
}
@@ -57,7 +63,7 @@ var ShellInfo = class {
}
};
-var OverviewActor = GObject.registerClass(
+export const OverviewActor = GObject.registerClass(
class OverviewActor extends St.BoxLayout {
_init() {
super._init({
@@ -83,6 +89,7 @@ class OverviewActor extends St.BoxLayout {
}
runStartupAnimation(callback) {
+ log('animating...');
this._controls.runStartupAnimation(callback);
}
@@ -99,7 +106,7 @@ class OverviewActor extends St.BoxLayout {
}
});
-var Overview = class extends Signals.EventEmitter {
+export class Overview extends Signals.EventEmitter {
constructor() {
super();
@@ -641,6 +648,7 @@ var Overview = class extends Signals.EventEmitter {
}
runStartupAnimation(callback) {
+ log('trackin')
Main.panel.style = 'transition-duration: 0ms;';
this._shown = true;
@@ -654,6 +662,7 @@ var Overview = class extends Signals.EventEmitter {
Meta.disable_unredirect_for_display(global.display);
this.emit('showing');
+ log('SHOWING');
this._overview.runStartupAnimation(() => {
if (!this._syncGrab()) {
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index 6cbaa22ba..356e7a653 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -1,33 +1,41 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ControlsManager */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const AppDisplay = imports.ui.appDisplay;
-const Dash = imports.ui.dash;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
-const Overview = imports.ui.overview;
-const SearchController = imports.ui.searchController;
-const Util = imports.misc.util;
-const WindowManager = imports.ui.windowManager;
-const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
-const WorkspacesView = imports.ui.workspacesView;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AppDisplay from './appDisplay.js';
+import * as Dash from './dash.js';
+import * as Layout from './layout.js';
+import Main from './main.js';
+import * as Overview from './overview.js';
+import * as SearchController from './searchController.js';
+import * as Util from '../misc/util.js';
+import * as WindowManager from './windowManager.js';
+import * as WorkspaceThumbnail from './workspaceThumbnail.js';
+import * as WorkspacesView from './workspacesView.js';
const SMALL_WORKSPACE_RATIO = 0.15;
const DASH_MAX_HEIGHT_RATIO = 0.15;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
-var SIDE_CONTROLS_ANIMATION_TIME = Overview.ANIMATION_TIME;
+// TODO
+// import { ANIMATION_TIME as SIDE_CONTROLS_ANIMATION_TIME } from './overview.js';
+// export { ANIMATION_TIME as SIDE_CONTROLS_ANIMATION_TIME } from './overview.js';
+export let SIDE_CONTROLS_ANIMATION_TIME = 250;
-var ControlsState = {
+export const ControlsState = {
HIDDEN: 0,
WINDOW_PICKER: 1,
APP_GRID: 2,
};
-var ControlsManagerLayout = GObject.registerClass(
+export const ControlsManagerLayout = GObject.registerClass(
class ControlsManagerLayout extends Clutter.BoxLayout {
_init(searchEntry, appDisplay, workspacesDisplay, workspacesThumbnails,
searchController, dash, stateAdjustment) {
@@ -118,11 +126,13 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
this.hookup_style(container);
}
+ /** @returns {[number, number]} */
vfunc_get_preferred_width(_container, _forHeight) {
// The MonitorConstraint will allocate us a fixed size anyway
return [0, 0];
}
+ /** @returns {[number, number]} */
vfunc_get_preferred_height(_container, _forWidth) {
// The MonitorConstraint will allocate us a fixed size anyway
return [0, 0];
@@ -241,7 +251,7 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
}
});
-var OverviewAdjustment = GObject.registerClass({
+export const OverviewAdjustment = GObject.registerClass({
Properties: {
'gesture-in-progress': GObject.ParamSpec.boolean(
'gesture-in-progress', 'Gesture in progress', 'Gesture in progress',
@@ -249,6 +259,9 @@ var OverviewAdjustment = GObject.registerClass({
false),
},
}, class OverviewAdjustment extends St.Adjustment {
+ /** @type {boolean} */
+ gestureInProgress;
+
_init(actor) {
super._init({
actor,
@@ -262,12 +275,14 @@ var OverviewAdjustment = GObject.registerClass({
const currentState = this.value;
const transition = this.get_transition('value');
- let initialState = transition
+ /** @type {number} */
+ let initialState = (transition
? transition.get_interval().peek_initial_value()
- : currentState;
- let finalState = transition
+ : currentState);
+ /** @type {number} */
+ let finalState = (transition
? transition.get_interval().peek_final_value()
- : currentState;
+ : currentState);
if (initialState > finalState) {
initialState = Math.ceil(initialState);
@@ -292,7 +307,7 @@ var OverviewAdjustment = GObject.registerClass({
}
});
-var ControlsManager = GObject.registerClass(
+export const ControlsManager = GObject.registerClass(
class ControlsManager extends St.Widget {
_init() {
super._init({
@@ -375,6 +390,7 @@ class ControlsManager extends St.Widget {
this.add_child(this._thumbnailsBox);
this.add_child(this._workspacesDisplay);
+ /** @type {ControlsManagerLayout["prototype"]} */
this.layout_manager = new ControlsManagerLayout(
this._searchEntryBin,
this._appDisplay,
@@ -718,7 +734,7 @@ class ControlsManager extends St.Widget {
}
getWorkspacesBoxForState(state) {
- return this.layoutManager.getWorkspacesBoxForState(state);
+ return this.layout_manager.getWorkspacesBoxForState(state);
}
gestureBegin(tracker) {
diff --git a/js/ui/padOsd.js b/js/ui/padOsd.js
index 1f3abe14c..c71b24d59 100644
--- a/js/ui/padOsd.js
+++ b/js/ui/padOsd.js
@@ -1,15 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PadOsd, PadOsdService */
-const { Atk, Clutter, GDesktopEnums, Gio,
- GLib, GObject, Gtk, Meta, Pango, Rsvg, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
-const Layout = imports.ui.layout;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GDesktopEnums from 'gi://GDesktopEnums';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import Rsvg from 'gi://Rsvg';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
+
+import Main from './main.js';
+import * as PopupMenu from './popupMenu.js';
+import * as Layout from './layout.js';
+
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const ACTIVE_COLOR = "#729fcf";
@@ -22,9 +31,13 @@ const CCW = 1;
const UP = 0;
const DOWN = 1;
-var PadChooser = GObject.registerClass({
+export const PadChooser = GObject.registerClass({
Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } },
}, class PadChooser extends St.Button {
+ /**
+ * @param {*} device
+ * @param {*} groupDevices
+ */
_init(device, groupDevices) {
super._init({
style_class: 'pad-chooser-button',
@@ -88,7 +101,7 @@ var PadChooser = GObject.registerClass({
}
});
-var KeybindingEntry = GObject.registerClass({
+export const KeybindingEntry = GObject.registerClass({
Signals: { 'keybinding-edited': { param_types: [GObject.TYPE_STRING] } },
}, class KeybindingEntry extends St.Entry {
_init() {
@@ -109,7 +122,7 @@ var KeybindingEntry = GObject.registerClass({
}
});
-var ActionComboBox = GObject.registerClass({
+export const ActionComboBox = GObject.registerClass({
Signals: { 'action-selected': { param_types: [GObject.TYPE_INT] } },
}, class ActionComboBox extends St.Button {
_init() {
@@ -191,7 +204,7 @@ var ActionComboBox = GObject.registerClass({
}
});
-var ActionEditor = GObject.registerClass({
+export const ActionEditor = GObject.registerClass({
Signals: { 'done': {} },
}, class ActionEditor extends St.Widget {
_init() {
@@ -275,7 +288,7 @@ var ActionEditor = GObject.registerClass({
}
});
-var PadDiagram = GObject.registerClass({
+export const PadDiagram = GObject.registerClass({
Properties: {
'left-handed': GObject.ParamSpec.boolean('left-handed',
'left-handed', 'Left handed',
@@ -368,7 +381,7 @@ var PadDiagram = GObject.registerClass({
let css = this._css;
for (let i = 0; i < this._activeButtons.length; i++) {
- let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
+ let ch = String.fromCharCode('A'.charCodeAt(0) + this._activeButtons[i]);
css += '.%s.Leader { stroke: %s !important; }'.format(ch, ACTIVE_COLOR);
css += '.%s.Button { stroke: %s !important; fill: %s !important; }'.format(ch, ACTIVE_COLOR, ACTIVE_COLOR);
}
@@ -387,7 +400,8 @@ var PadDiagram = GObject.registerClass({
svgData += this._wrappingSvgFooter();
let istream = new Gio.MemoryInputStream();
- istream.add_bytes(new GLib.Bytes(svgData));
+ // FIXME
+ istream.add_bytes(imports.byteArray.fromString(svgData));
return Rsvg.Handle.new_from_stream_sync(istream,
Gio.File.new_for_path(this._imagePath), 0, null);
@@ -495,7 +509,7 @@ var PadDiagram = GObject.registerClass({
}
_getButtonLabels(button) {
- let ch = String.fromCharCode('A'.charCodeAt() + button);
+ let ch = String.fromCharCode('A'.charCodeAt(0) + button);
let labelName = 'Label%s'.format(ch);
let leaderName = 'Leader%s'.format(ch);
return [labelName, leaderName];
@@ -618,12 +632,19 @@ var PadDiagram = GObject.registerClass({
}
});
-var PadOsd = GObject.registerClass({
+export const PadOsd = GObject.registerClass({
Signals: {
'pad-selected': { param_types: [Clutter.InputDevice.$gtype] },
'closed': {},
},
}, class PadOsd extends St.BoxLayout {
+ /**
+ * @param {*} padDevice
+ * @param {*} settings
+ * @param {*} imagePath
+ * @param {*} editionMode
+ * @param {*} monitorIndex
+ */
_init(padDevice, settings, imagePath, editionMode, monitorIndex) {
super._init({
style_class: 'pad-osd-window',
@@ -894,19 +915,19 @@ var PadOsd = GObject.registerClass({
}
_startButtonActionEdition(button) {
- let ch = String.fromCharCode('A'.charCodeAt() + button);
+ let ch = String.fromCharCode('A'.charCodeAt(0) + button);
let key = 'button%s'.format(ch);
this._startActionEdition(key, Meta.PadActionType.BUTTON, button);
}
_startRingActionEdition(ring, dir, mode) {
- let ch = String.fromCharCode('A'.charCodeAt() + ring);
+ let ch = String.fromCharCode('A'.charCodeAt(0) + ring);
let key = 'ring%s-%s-mode-%d'.format(ch, dir == CCW ? 'ccw' : 'cw', mode);
this._startActionEdition(key, Meta.PadActionType.RING, ring, dir, mode);
}
_startStripActionEdition(strip, dir, mode) {
- let ch = String.fromCharCode('A'.charCodeAt() + strip);
+ let ch = String.fromCharCode('A'.charCodeAt(0) + strip);
let key = 'strip%s-%s-mode-%d'.format(ch, dir == UP ? 'up' : 'down', mode);
this._startActionEdition(key, Meta.PadActionType.STRIP, strip, dir, mode);
}
@@ -944,7 +965,7 @@ var PadOsd = GObject.registerClass({
const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd');
-var PadOsdService = class extends Signals.EventEmitter {
+export class PadOsdService extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/ui/pageIndicators.js b/js/ui/pageIndicators.js
index 63a31d679..be2c6f99b 100644
--- a/js/ui/pageIndicators.js
+++ b/js/ui/pageIndicators.js
@@ -1,14 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PageIndicators */
-const { Clutter, Graphene, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Graphene from 'gi://Graphene';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
const INDICATOR_INACTIVE_OPACITY = 128;
const INDICATOR_INACTIVE_OPACITY_HOVER = 255;
const INDICATOR_INACTIVE_SCALE = 2 / 3;
const INDICATOR_INACTIVE_SCALE_PRESSED = 0.5;
-var PageIndicators = GObject.registerClass({
+export const PageIndicators = GObject.registerClass({
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } },
}, class PageIndicators extends St.BoxLayout {
_init(orientation = Clutter.Orientation.VERTICAL) {
@@ -29,6 +32,9 @@ var PageIndicators = GObject.registerClass({
this._orientation = orientation;
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(forWidth) {
// We want to request the natural height of all our children as our
// natural height, so we chain up to St.BoxLayout, but we only request 0
diff --git a/js/ui/panel.js b/js/ui/panel.js
index dafba690a..5af13d239 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -1,23 +1,29 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Panel */
-const { Atk, Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
-const Cairo = imports.cairo;
-
-const Animation = imports.ui.animation;
-const { AppMenu } = imports.ui.appMenu;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import Cairo from 'cairo';
+
+import * as Animation from './animation.js';
+import { AppMenu } from './appMenu.js';
const Config = imports.misc.config;
-const CtrlAltTab = imports.ui.ctrlAltTab;
-const DND = imports.ui.dnd;
-const Overview = imports.ui.overview;
-const PopupMenu = imports.ui.popupMenu;
-const PanelMenu = imports.ui.panelMenu;
-const Main = imports.ui.main;
+import * as CtrlAltTab from './ctrlAltTab.js';
+import * as DND from './dnd.js';
+import * as Overview from './overview.js';
+import * as PopupMenu from './popupMenu.js';
+import * as PanelMenu from './panelMenu.js';
+import Main from './main.js';
-var PANEL_ICON_SIZE = 16;
-var APP_MENU_ICON_MARGIN = 0;
+export let PANEL_ICON_SIZE = 16;
+export let APP_MENU_ICON_MARGIN = 0;
-var BUTTON_DND_ACTIVATION_TIMEOUT = 250;
+export let BUTTON_DND_ACTIVATION_TIMEOUT = 250;
/**
* AppMenuButton:
@@ -27,7 +33,7 @@ var BUTTON_DND_ACTIVATION_TIMEOUT = 250;
* this menu also handles startup notification for it. So when we
* have an active startup notification, we switch modes to display that.
*/
-var AppMenuButton = GObject.registerClass({
+export const AppMenuButton = GObject.registerClass({
Signals: { 'changed': {} },
}, class AppMenuButton extends PanelMenu.Button {
_init(panel) {
@@ -258,7 +264,7 @@ var AppMenuButton = GObject.registerClass({
}
});
-var ActivitiesButton = GObject.registerClass(
+export const ActivitiesButton = GObject.registerClass(
class ActivitiesButton extends PanelMenu.Button {
_init() {
super._init(0.0, null, true);
@@ -294,6 +300,8 @@ class ActivitiesButton extends PanelMenu.Button {
GLib.source_remove(this._xdndTimeOut);
this._xdndTimeOut = GLib.timeout_add(GLib.PRIORITY_DEFAULT, BUTTON_DND_ACTIVATION_TIMEOUT, () => {
this._xdndToggleOverview();
+
+ return false;
});
GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
@@ -344,7 +352,7 @@ class ActivitiesButton extends PanelMenu.Button {
}
});
-var PanelCorner = GObject.registerClass(
+export const PanelCorner = GObject.registerClass(
class PanelCorner extends St.DrawingArea {
_init(side) {
this._side = side;
@@ -535,6 +543,9 @@ class AggregateLayout extends Clutter.BoxLayout {
this.layout_changed();
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
let themeNode = container.get_theme_node();
let minWidth = themeNode.get_min_width();
@@ -550,38 +561,44 @@ class AggregateLayout extends Clutter.BoxLayout {
}
});
-var AggregateMenu = GObject.registerClass(
+
+
+export const AggregateMenu = GObject.registerClass(
class AggregateMenu extends PanelMenu.Button {
_init() {
super._init(0.0, C_("System menu in the top bar", "System"), false);
this.menu.actor.add_style_class_name('aggregate-menu');
- let menuLayout = new AggregateLayout();
- this.menu.box.set_layout_manager(menuLayout);
+ this._menuLayout = new AggregateLayout();
+ this.menu.box.set_layout_manager(this._menuLayout);
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
this.add_child(this._indicators);
+ }
+ async _asyncInit() {
if (Config.HAVE_NETWORKMANAGER)
- this._network = new imports.ui.status.network.NMApplet();
+ this._network = new ((await import('./status/network.js')).NMApplet)();
else
this._network = null;
if (Config.HAVE_BLUETOOTH)
- this._bluetooth = new imports.ui.status.bluetooth.Indicator();
+ this._bluetooth = new ((await import('./status/bluetooth.js')).Indicator)();
else
this._bluetooth = null;
- this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
- this._power = new imports.ui.status.power.Indicator();
- this._powerProfiles = new imports.ui.status.powerProfiles.Indicator();
- this._rfkill = new imports.ui.status.rfkill.Indicator();
- this._volume = new imports.ui.status.volume.Indicator();
- this._brightness = new imports.ui.status.brightness.Indicator();
- this._system = new imports.ui.status.system.Indicator();
- this._location = new imports.ui.status.location.Indicator();
- this._nightLight = new imports.ui.status.nightLight.Indicator();
- this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
+ const menuLayout = this._menuLayout;
+
+ this._remoteAccess = new ((await import('./status/remoteAccess.js')).RemoteAccessApplet)();
+ this._powerProfiles = new ((await import('./status/powerProfiles.js')).Indicator)();
+ this._power = new ((await import('./status/power.js')).Indicator)();
+ this._rfkill = new ((await import('./status/rfkill.js')).Indicator)();
+ this._volume = new ((await import('./status/volume.js')).Indicator)();
+ this._brightness = new ((await import('./status/brightness.js')).Indicator)();
+ this._system = new ((await import('./status/system.js')).Indicator)();
+ this._location = new ((await import('./status/location.js')).Indicator)();
+ this._nightLight = new ((await import('./status/nightLight.js')).Indicator)();
+ this._thunderbolt = new ((await import('./status/thunderbolt.js')).Indicator)();
this._unsafeMode = new UnsafeModeIndicator();
this._indicators.add_child(this._remoteAccess);
@@ -624,17 +641,22 @@ class AggregateMenu extends PanelMenu.Button {
}
});
+import {DateMenuButton} from './dateMenu.js';
+import {ATIndicator} from './status/accessibility.js';
+import {InputSourceIndicator} from './status/keyboard.js';
+import {DwellClickIndicator} from './status/dwellClick.js';
+
const PANEL_ITEM_IMPLEMENTATIONS = {
'activities': ActivitiesButton,
'aggregateMenu': AggregateMenu,
'appMenu': AppMenuButton,
- 'dateMenu': imports.ui.dateMenu.DateMenuButton,
- 'a11y': imports.ui.status.accessibility.ATIndicator,
- 'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
- 'dwellClick': imports.ui.status.dwellClick.DwellClickIndicator,
+ 'dateMenu': DateMenuButton,
+ 'a11y': ATIndicator,
+ 'keyboard': InputSourceIndicator,
+ 'dwellClick': DwellClickIndicator,
};
-var Panel = GObject.registerClass(
+export const Panel = GObject.registerClass(
class Panel extends St.Widget {
_init() {
super._init({ name: 'panel',
@@ -673,13 +695,26 @@ class Panel extends St.Widget {
Main.layoutManager.panelBox.add(this);
Main.ctrlAltTabManager.addGroup(this, _("Top Bar"), 'focus-top-bar-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
-
- Main.sessionMode.connect('updated', this._updatePanel.bind(this));
+ log('updating panel...');
+ Main.sessionMode.connect('updated', () => {
+ this._updatePanel().then(() => {
+ log('Panel Updated!');
+ }).catch(err => {
+ logError(err)
+ });
+ });
global.display.connect('workareas-changed', () => this.queue_relayout());
- this._updatePanel();
+ this._updatePanel().then(() => {
+ log('Panel Updated! (1)');
+ }).catch(err => {
+ logError(err)
+ });
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(_forHeight) {
let primaryMonitor = Main.layoutManager.primaryMonitor;
@@ -863,12 +898,14 @@ class Panel extends St.Widget {
return this._leftBox.opacity;
}
- _updatePanel() {
+ async _updatePanel() {
+ try {
+ log('Updating panel...');
let panel = Main.sessionMode.panel;
this._hideIndicators();
- this._updateBox(panel.left, this._leftBox);
- this._updateBox(panel.center, this._centerBox);
- this._updateBox(panel.right, this._rightBox);
+ await this._updateBox(panel.left, this._leftBox);
+ await this._updateBox(panel.center, this._centerBox);
+ await this._updateBox(panel.right, this._rightBox);
if (panel.left.includes('dateMenu'))
Main.messageTray.bannerAlignment = Clutter.ActorAlign.START;
@@ -892,6 +929,10 @@ class Panel extends St.Widget {
this._leftCorner.setStyleParent(this._leftBox);
this._rightCorner.setStyleParent(this._rightBox);
}
+ }catch(error) {
+ log('FAILED TO UPDATE PANEL...');
+ logError(error);
+ }
}
_hideIndicators() {
@@ -903,7 +944,7 @@ class Panel extends St.Widget {
}
}
- _ensureIndicator(role) {
+ async _ensureIndicator(role) {
let indicator = this.statusArea[role];
if (!indicator) {
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
@@ -912,17 +953,22 @@ class Panel extends St.Widget {
return null;
}
indicator = new constructor(this);
+
+ // TODO
+ if (indicator._asyncInit)
+ await indicator._asyncInit();
+
this.statusArea[role] = indicator;
}
return indicator;
}
- _updateBox(elements, box) {
+ async _updateBox(elements, box) {
let nChildren = box.get_n_children();
for (let i = 0; i < elements.length; i++) {
let role = elements[i];
- let indicator = this._ensureIndicator(role);
+ let indicator = await this._ensureIndicator(role);
if (indicator == null)
continue;
diff --git a/js/ui/panelMenu.js b/js/ui/panelMenu.js
index ccfe97613..0736b666f 100644
--- a/js/ui/panelMenu.js
+++ b/js/ui/panelMenu.js
@@ -1,12 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Button, SystemIndicator */
-const { Atk, Clutter, GObject, St } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
+import Main from './main.js';
+import * as PopupMenu from './popupMenu.js';
-var ButtonBox = GObject.registerClass(
+export const ButtonBox = GObject.registerClass(
class ButtonBox extends St.Widget {
_init(params) {
const {
@@ -34,6 +37,9 @@ class ButtonBox extends St.Widget {
this._natHPadding = themeNode.get_length('-natural-hpadding');
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(_forHeight) {
let child = this.get_first_child();
let minimumSize, naturalSize;
@@ -49,6 +55,9 @@ class ButtonBox extends St.Widget {
return [minimumSize, naturalSize];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(_forWidth) {
let child = this.get_first_child();
@@ -91,7 +100,7 @@ class ButtonBox extends St.Widget {
}
});
-var Button = GObject.registerClass({
+export const Button = GObject.registerClass({
Signals: { 'menu-set': {} },
}, class PanelMenuButton extends ButtonBox {
_init(menuAlignment, nameText, dontCreateMenu) {
@@ -106,7 +115,7 @@ var Button = GObject.registerClass({
if (dontCreateMenu)
this.menu = new PopupMenu.PopupDummyMenu(this);
else
- this.setMenu(new PopupMenu.PopupMenu(this, menuAlignment, St.Side.TOP, 0));
+ this.setMenu(new PopupMenu.PopupMenu(this, menuAlignment, St.Side.TOP));
}
setSensitive(sensitive) {
@@ -180,7 +189,7 @@ var Button = GObject.registerClass({
// measures are in logical pixels, so make sure to consider the scale
// factor when computing max-height
let maxHeight = Math.round((workArea.height - verticalMargins) / scaleFactor);
- this.menu.actor.style = 'max-height: %spx;'.format(maxHeight);
+ this.menu.actor.style = 'max-height: %spx;'.format(maxHeight.toFixed(0));
}
_onDestroy() {
@@ -197,7 +206,7 @@ var Button = GObject.registerClass({
* of an icon and a menu section, which will be composed into the
* aggregate menu.
*/
-var SystemIndicator = GObject.registerClass(
+export const SystemIndicator = GObject.registerClass(
class SystemIndicator extends St.BoxLayout {
_init() {
super._init({
diff --git a/js/ui/pointerA11yTimeout.js b/js/ui/pointerA11yTimeout.js
index 263cc3eaf..40dd0abb5 100644
--- a/js/ui/pointerA11yTimeout.js
+++ b/js/ui/pointerA11yTimeout.js
@@ -1,11 +1,16 @@
/* exported PointerA11yTimeout */
-const { Clutter, GObject, Meta, St } = imports.gi;
-const Main = imports.ui.main;
-const Cairo = imports.cairo;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
+
+import Main from './main.js';
+
+import Cairo from 'gi://cairo';
const SUCCESS_ZOOM_OUT_DURATION = 150;
-var PieTimer = GObject.registerClass({
+export const PieTimer = GObject.registerClass({
Properties: {
'angle': GObject.ParamSpec.double(
'angle', 'angle', 'angle',
@@ -106,7 +111,7 @@ var PieTimer = GObject.registerClass({
}
});
-var PointerA11yTimeout = class PointerA11yTimeout {
+export class PointerA11yTimeout {
constructor() {
let seat = Clutter.get_default_backend().get_default_seat();
diff --git a/js/ui/pointerWatcher.js b/js/ui/pointerWatcher.js
index 2af35b617..4ab11599a 100644
--- a/js/ui/pointerWatcher.js
+++ b/js/ui/pointerWatcher.js
@@ -1,24 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getPointerWatcher */
-const { GLib } = imports.gi;
+import GLib from 'gi://GLib';
// We stop polling if the user is idle for more than this amount of time
-var IDLE_TIME = 1000;
+export const IDLE_TIME = 1000;
// This file implements a reasonably efficient system for tracking the position
// of the mouse pointer. We simply query the pointer from the X server in a loop,
// but we turn off the polling when the user is idle.
let _pointerWatcher = null;
-function getPointerWatcher() {
+export function getPointerWatcher() {
if (_pointerWatcher == null)
_pointerWatcher = new PointerWatcher();
return _pointerWatcher;
}
-var PointerWatch = class {
+export class PointerWatch {
constructor(watcher, interval, callback) {
this.watcher = watcher;
this.interval = interval;
@@ -33,7 +33,7 @@ var PointerWatch = class {
}
};
-var PointerWatcher = class {
+export class PointerWatcher {
constructor() {
this._idleMonitor = global.backend.get_core_idle_monitor();
this._idleMonitor.add_idle_watch(IDLE_TIME, this._onIdleMonitorBecameIdle.bind(this));
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index f4e760bfb..e818083b2 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -3,14 +3,21 @@
PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */
-const { Atk, Clutter, Gio, GObject, Graphene, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const BoxPointer = imports.ui.boxpointer;
-const GrabHelper = imports.ui.grabHelper;
-const Main = imports.ui.main;
-
-var Ornament = {
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Graphene from 'gi://Graphene';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
+
+import * as BoxPointer from './boxpointer.js';
+import * as GrabHelper from './grabHelper.js';
+import Main from './main.js';
+
+/** @enum {number} */
+export const Ornament = {
NONE: 0,
DOT: 1,
CHECK: 2,
@@ -30,7 +37,7 @@ function isPopupMenuItemVisible(child) {
* @param {St.Side} side - Side to which the arrow points.
* @returns {St.Icon} a new arrow icon
*/
-function arrowIcon(side) {
+export function arrowIcon(side) {
let iconName;
switch (side) {
case St.Side.TOP:
@@ -56,7 +63,9 @@ function arrowIcon(side) {
return arrow;
}
-var PopupBaseMenuItem = GObject.registerClass({
+/** @typedef {{active?: boolean} & Partial<Pick<St.BoxLayout.ConstructorProperties, 'style_class' | 'can_focus' | 'hover' | 'activate' | 'reactive'>>} PopupBaseMenuItemParams */
+
+export const PopupBaseMenuItem = GObject.registerClass({
Properties: {
'active': GObject.ParamSpec.boolean('active', 'active', 'active',
GObject.ParamFlags.READWRITE,
@@ -69,7 +78,7 @@ var PopupBaseMenuItem = GObject.registerClass({
'activate': { param_types: [Clutter.Event.$gtype] },
},
}, class PopupBaseMenuItem extends St.BoxLayout {
- _init(params = {}) {
+ _init(params = {}, ..._) {
const {
reactive = true,
activate = true,
@@ -85,6 +94,11 @@ var PopupBaseMenuItem = GObject.registerClass({
accessible_role: Atk.Role.MENU_ITEM });
this._delegate = this;
+ /** @type {any} */
+ this.prop
+ /** @type {any} */
+ this.radioGroup
+
this._ornament = Ornament.NONE;
this._ornamentLabel = new St.Label({ style_class: 'popup-menu-ornament' });
this.add(this._ornamentLabel);
@@ -267,9 +281,18 @@ var PopupBaseMenuItem = GObject.registerClass({
}
});
-var PopupMenuItem = GObject.registerClass(
+/**
+ * @typedef {object} PopupMenuItemParams
+ * @property {string} [text]
+ * @property {boolean} [active]
+ */
+
+export const PopupMenuItem = GObject.registerClass(
class PopupMenuItem extends PopupBaseMenuItem {
- _init(text, params) {
+ /**
+ * @param {PopupMenuItemParams & PopupBaseMenuItemParams} [params]
+ */
+ _init(text, params) {
super._init(params);
this.label = new St.Label({ text });
@@ -279,8 +302,11 @@ class PopupMenuItem extends PopupBaseMenuItem {
});
-var PopupSeparatorMenuItem = GObject.registerClass(
+export const PopupSeparatorMenuItem = GObject.registerClass(
class PopupSeparatorMenuItem extends PopupBaseMenuItem {
+ /**
+ * @param {string | any} text
+ */
_init(text) {
super._init({
style_class: 'popup-separator-menu-item',
@@ -310,7 +336,7 @@ class PopupSeparatorMenuItem extends PopupBaseMenuItem {
}
});
-var Switch = GObject.registerClass({
+export const Switch = GObject.registerClass({
Properties: {
'state': GObject.ParamSpec.boolean(
'state', 'state', 'state',
@@ -350,10 +376,10 @@ var Switch = GObject.registerClass({
}
});
-var PopupSwitchMenuItem = GObject.registerClass({
+export const PopupSwitchMenuItem = GObject.registerClass({
Signals: { 'toggled': { param_types: [GObject.TYPE_BOOLEAN] } },
}, class PopupSwitchMenuItem extends PopupBaseMenuItem {
- _init(text, active, params) {
+ _init(text, active, params) {
super._init(params);
this.label = new St.Label({ text });
@@ -434,8 +460,13 @@ var PopupSwitchMenuItem = GObject.registerClass({
}
});
-var PopupImageMenuItem = GObject.registerClass(
+export const PopupImageMenuItem = GObject.registerClass(
class PopupImageMenuItem extends PopupBaseMenuItem {
+ /**
+ * @param {string | any} text
+ * @param {string | Gio.Icon} [icon]
+ * @param {PopupBaseMenuItemParams} [params]
+ */
_init(text, icon, params) {
super._init(params);
@@ -446,9 +477,14 @@ class PopupImageMenuItem extends PopupBaseMenuItem {
this.add_child(this.label);
this.label_actor = this.label;
- this.setIcon(icon);
+ if (icon) {
+ this.setIcon(icon);
+ }
}
+ /**
+ * @param {string | Gio.Icon} icon
+ */
setIcon(icon) {
// The 'icon' parameter can be either a Gio.Icon or a string.
if (icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
@@ -458,7 +494,7 @@ class PopupImageMenuItem extends PopupBaseMenuItem {
}
});
-var PopupMenuBase = class extends Signals.EventEmitter {
+export class PopupMenuBase extends Signals.EventEmitter {
constructor(sourceActor, styleClass) {
super();
@@ -467,6 +503,10 @@ var PopupMenuBase = class extends Signals.EventEmitter {
this.sourceActor = sourceActor;
this.focusActor = sourceActor;
+
+ /** @type {St.Widget} */
+ this.actor;
+
this._parent = null;
this.box = new St.BoxLayout({
@@ -695,6 +735,10 @@ var PopupMenuBase = class extends Signals.EventEmitter {
}
}
+ /**
+ * @param {PopupMenuBase | PopupBaseMenuItem["prototype"]} menuItem
+ * @param {number} [position]
+ */
addMenuItem(menuItem, position) {
let beforeItem = null;
if (position == undefined) {
@@ -774,9 +818,12 @@ var PopupMenuBase = class extends Signals.EventEmitter {
}
_getMenuItems() {
- return this.box.get_children().map(a => a._delegate).filter(item => {
- return item instanceof PopupBaseMenuItem || item instanceof PopupMenuSection;
- });
+ return this.box.get_children().map(a => a._delegate).filter(
+ /**
+ * @returns {item is PopupMenuBase | PopupMenuSection}
+ */
+ item => item instanceof PopupBaseMenuItem || item instanceof PopupMenuSection
+ );
}
get firstMenuItem() {
@@ -791,6 +838,20 @@ var PopupMenuBase = class extends Signals.EventEmitter {
return this._getMenuItems().length;
}
+ /**
+ * @param {BoxPointer.PopupAnimation} _animation
+ */
+ open(_animation) {
+ throw new GObject.NotImplementedError(`open in ${this.constructor.name}`);
+ }
+
+ /**
+ * @param {BoxPointer.PopupAnimation} [_animation]
+ */
+ close(_animation) {
+ throw new GObject.NotImplementedError(`close in ${this.constructor.name}`);
+ }
+
removeAll() {
let children = this._getMenuItems();
for (let i = 0; i < children.length; i++) {
@@ -818,7 +879,7 @@ var PopupMenuBase = class extends Signals.EventEmitter {
}
};
-var PopupMenu = class extends PopupMenuBase {
+export class PopupMenu extends PopupMenuBase {
constructor(sourceActor, arrowAlignment, arrowSide) {
super(sourceActor, 'popup-menu-content');
@@ -969,7 +1030,7 @@ var PopupMenu = class extends PopupMenuBase {
}
};
-var PopupDummyMenu = class extends Signals.EventEmitter {
+export class PopupDummyMenu extends Signals.EventEmitter {
constructor(sourceActor) {
super();
@@ -1001,7 +1062,7 @@ var PopupDummyMenu = class extends Signals.EventEmitter {
}
};
-var PopupSubMenu = class extends PopupMenuBase {
+export class PopupSubMenu extends PopupMenuBase {
constructor(sourceActor, sourceArrow) {
super(sourceActor);
@@ -1146,7 +1207,7 @@ var PopupSubMenu = class extends PopupMenuBase {
* can add it to another menu), but is completely transparent
* to the user
*/
-var PopupMenuSection = class extends PopupMenuBase {
+export class PopupMenuSection extends PopupMenuBase {
constructor() {
super();
@@ -1166,7 +1227,7 @@ var PopupMenuSection = class extends PopupMenuBase {
}
};
-var PopupSubMenuMenuItem = GObject.registerClass(
+export const PopupSubMenuMenuItem = GObject.registerClass(
class PopupSubMenuMenuItem extends PopupBaseMenuItem {
_init(text, wantIcon) {
super._init();
@@ -1287,7 +1348,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
/* Basic implementation of a menu manager.
* Call addMenu to add menus
*/
-var PopupMenuManager = class {
+export class PopupMenuManager {
constructor(owner, grabParams = {}) {
this._grabHelper = new GrabHelper.GrabHelper(owner, {
actionMode: Shell.ActionMode.POPUP,
diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js
index 137516bdc..72b227765 100644
--- a/js/ui/remoteSearch.js
+++ b/js/ui/remoteSearch.js
@@ -1,9 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported loadRemoteSearchProviders */
-const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
+import GdkPixbuf from 'gi://GdkPixbuf';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const FileUtils = imports.misc.fileUtils;
+import * as FileUtils from '../misc/fileUtilsModule.js';
const KEY_FILE_GROUP = 'Shell Search Provider';
@@ -57,10 +61,10 @@ const SearchProvider2Iface = `
</interface>
</node>`;
-var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
-var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
+export const SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
+export const SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
-function loadRemoteSearchProviders(searchSettings, callback) {
+export function loadRemoteSearchProviders(searchSettings, callback) {
let objectPaths = {};
let loadedProviders = [];
@@ -104,9 +108,9 @@ function loadRemoteSearchProviders(searchSettings, callback) {
// ignore error
}
- let version = '1';
+ let version = 1;
try {
- version = keyfile.get_string(group, 'Version');
+ version = Number.parseInt(keyfile.get_string(group, 'Version'), 10);
} catch (e) {
// ignore error
}
@@ -187,7 +191,7 @@ function loadRemoteSearchProviders(searchSettings, callback) {
callback(loadedProviders);
}
-var RemoteSearchProvider = class {
+export class RemoteSearchProvider {
constructor(appInfo, dbusName, dbusPath, autoStart, proxyInfo) {
if (!proxyInfo)
proxyInfo = SearchProviderProxyInfo;
@@ -210,6 +214,7 @@ var RemoteSearchProvider = class {
this.id = appInfo.get_id();
this.isRemoteProvider = true;
this.canLaunchSearch = false;
+ this.defaultEnabled = false;
}
createIcon(size, meta) {
@@ -318,7 +323,7 @@ var RemoteSearchProvider = class {
}
};
-var RemoteSearchProvider2 = class extends RemoteSearchProvider {
+export class RemoteSearchProvider2 extends RemoteSearchProvider {
constructor(appInfo, dbusName, dbusPath, autoStart) {
super(appInfo, dbusName, dbusPath, autoStart, SearchProvider2ProxyInfo);
diff --git a/js/ui/ripples.js b/js/ui/ripples.js
index f38062228..d9d6b8707 100644
--- a/js/ui/ripples.js
+++ b/js/ui/ripples.js
@@ -1,10 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Ripples */
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
// Shamelessly copied from the layout "hotcorner" ripples implementation
-var Ripples = class Ripples {
+export class Ripples {
constructor(px, py, styleClass) {
this._x = 0;
this._y = 0;
diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js
index cf835972e..a3cbf7ab2 100644
--- a/js/ui/runDialog.js
+++ b/js/ui/runDialog.js
@@ -1,14 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported RunDialog */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
-const ShellEntry = imports.ui.shellEntry;
-const Util = imports.misc.util;
-const History = imports.misc.history;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Dialog from './dialog.js';
+import Main from './main.js';
+import * as ModalDialog from './modalDialog.js';
+import * as ShellEntry from './shellEntry.js';
+import * as Util from '../misc/util.js';
+import * as History from '../misc/history.js';
const HISTORY_KEY = 'command-history';
@@ -19,7 +25,7 @@ const TERMINAL_SCHEMA = 'org.gnome.desktop.default-applications.terminal';
const EXEC_KEY = 'exec';
const EXEC_ARG_KEY = 'exec-arg';
-var RunDialog = GObject.registerClass(
+export const RunDialog = GObject.registerClass(
class RunDialog extends ModalDialog.ModalDialog {
_init() {
super._init({
@@ -251,6 +257,6 @@ class RunDialog extends ModalDialog.ModalDialog {
if (this._lockdownSettings.get_boolean(DISABLE_COMMAND_LINE_KEY))
return;
- super.open();
+ return super.open();
}
});
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 431636463..95ee2c3c0 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -1,21 +1,27 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenShield */
-const { AccountsService, Clutter, Gio,
- GLib, Graphene, Meta, Shell, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const GnomeSession = imports.misc.gnomeSession;
-const OVirt = imports.gdm.oVirt;
-const LoginManager = imports.misc.loginManager;
-const Lightbox = imports.ui.lightbox;
-const Main = imports.ui.main;
-const Overview = imports.ui.overview;
-const MessageTray = imports.ui.messageTray;
-const ShellDBus = imports.ui.shellDBus;
-const SmartcardManager = imports.misc.smartcardManager;
-
-const { adjustAnimationTime } = imports.ui.environment;
+import AccountsService from 'gi://AccountsService';
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Graphene from 'gi://Graphene';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Signals from '../misc/signals.js';
+
+import * as GnomeSession from '../misc/gnomeSession.js';
+import * as OVirt from '../gdm/oVirt.js';
+import * as LoginManager from '../misc/loginManager.js';
+import * as Lightbox from './lightbox.js';
+import Main from './main.js';
+import * as Overview from './overview.js';
+import * as MessageTray from './messageTray.js';
+import * as ShellDBus from './shellDBus.js';
+import * as SmartcardManager from '../misc/smartcardManager.js';
+
+import { adjustAnimationTime } from './environment.js';
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
@@ -26,14 +32,15 @@ const DISABLE_LOCK_KEY = 'disable-lock-screen';
const LOCKED_STATE_STR = 'screenShield.locked';
+
// ScreenShield animation time
// - STANDARD_FADE_TIME is used when the session goes idle
// - MANUAL_FADE_TIME is used for lowering the shield when asked by the user,
// or when cancelling the dialog
// - CURTAIN_SLIDE_TIME is used when raising the shield before unlocking
-var STANDARD_FADE_TIME = 10000;
-var MANUAL_FADE_TIME = 300;
-var CURTAIN_SLIDE_TIME = 300;
+export let STANDARD_FADE_TIME = 10000;
+export let MANUAL_FADE_TIME = 300;
+export let CURTAIN_SLIDE_TIME = 300;
/**
* If you are setting org.gnome.desktop.session.idle-delay directly in dconf,
@@ -43,7 +50,7 @@ var CURTAIN_SLIDE_TIME = 300;
* This will ensure that the screen blanks at the right time when it fades out.
* https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependency.
*/
-var ScreenShield = class extends Signals.EventEmitter {
+export class ScreenShield extends Signals.EventEmitter {
constructor() {
super();
@@ -71,7 +78,8 @@ var ScreenShield = class extends Signals.EventEmitter {
this.actor.add_actor(this._lockScreenGroup);
this.actor.add_actor(this._lockDialogGroup);
- this._presence = new GnomeSession.Presence((proxy, error) => {
+ // FIXME
+ this._presence = GnomeSession.Presence((proxy, error) => {
if (error) {
logError(error, 'Error while reading gnome-session presence');
return;
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index bf537b7d6..3819938da 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -1,11 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenshotService */
-const { Clutter, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const GrabHelper = imports.ui.grabHelper;
-const Lightbox = imports.ui.lightbox;
-const Main = imports.ui.main;
+
+import * as GrabHelper from './grabHelper.js';
+import * as Lightbox from './lightbox.js';
+import Main from './main.js';
Gio._promisify(Shell.Screenshot.prototype, 'pick_color', 'pick_color_finish');
Gio._promisify(Shell.Screenshot.prototype, 'screenshot', 'screenshot_finish');
@@ -14,12 +21,12 @@ Gio._promisify(Shell.Screenshot.prototype,
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_area', 'screenshot_area_finish');
-const { loadInterfaceXML } = imports.misc.fileUtils;
-const { DBusSenderChecker } = imports.misc.util;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
+import { DBusSenderChecker } from '../misc/util.js';
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
-var ScreenshotService = class {
+export class ScreenshotService {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
@@ -108,10 +115,13 @@ var ScreenshotService = class {
for (let idx = 1; ; idx++) {
yield Gio.File.new_for_path(
- GLib.build_filenamev([path, '%s-%s.png'.format(filename, idx)]));
+ GLib.build_filenamev([path, '%s-%s.png'.format(filename, idx.toFixed(0))]));
}
}
+ /**
+ * @returns {[Gio.OutputStream, Gio.File | null] | [null, null]}
+ */
_createStream(filename, invocation) {
if (filename == '')
return [Gio.MemoryOutputStream.new_resizable(), null];
@@ -182,6 +192,15 @@ var ScreenshotService = class {
return [x, y, width, height];
}
+ // FIXME
+ /**
+ *
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ * @returns {[number, number, number, number]}
+ */
_unscaleArea(x, y, width, height) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
x /= scaleFactor;
@@ -337,7 +356,7 @@ var ScreenshotService = class {
}
};
-var SelectArea = GObject.registerClass(
+export const SelectArea = GObject.registerClass(
class SelectArea extends St.Widget {
_init() {
this._startX = -1;
@@ -438,7 +457,7 @@ class SelectArea extends St.Widget {
}
});
-var RecolorEffect = GObject.registerClass({
+export const RecolorEffect = GObject.registerClass({
Properties: {
color: GObject.ParamSpec.boxed(
'color', 'color', 'replacement color',
@@ -567,7 +586,7 @@ var RecolorEffect = GObject.registerClass({
}
});
-var PickPixel = GObject.registerClass(
+export const PickPixel = GObject.registerClass(
class PickPixel extends St.Widget {
_init(screenshot) {
super._init({ visible: false, reactive: true });
@@ -657,9 +676,9 @@ class PickPixel extends St.Widget {
}
});
-var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
+export const FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
-var Flashspot = GObject.registerClass(
+export const Flashspot = GObject.registerClass(
class Flashspot extends Lightbox.Lightbox {
_init(area) {
super._init(Main.uiGroup, {
diff --git a/js/ui/scripting.js b/js/ui/scripting.js
index aa405330c..e5746da61 100644
--- a/js/ui/scripting.js
+++ b/js/ui/scripting.js
@@ -3,13 +3,17 @@
destroyTestWindows, defineScriptEvent, scriptEvent,
collectStatistics, runPerfScript */
-const { Gio, GLib, Meta, Shell } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+
const Config = imports.misc.config;
-const Main = imports.ui.main;
-const Util = imports.misc.util;
+import Main from './main.js';
+import * as Util from '../misc/util.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
// This module provides functionality for driving the shell user interface
// in an automated fashion. The primary current use case for this is
@@ -20,7 +24,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
// When scripting an automated test we want to make a series of calls
// in a linear fashion, but we also want to be able to let the main
// loop run so actions can finish. For this reason we write the script
-// as an async function that uses await when it wants to let the main
+// as an async export function that uses await when it wants to let the main
// loop run.
//
// await Scripting.sleep(1000);
@@ -37,7 +41,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
* current script for the specified amount of time. Use as
* 'yield Scripting.sleep(500);'
*/
-function sleep(milliseconds) {
+export function sleep(milliseconds) {
return new Promise(resolve => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, milliseconds, () => {
resolve();
@@ -55,33 +59,33 @@ function sleep(milliseconds) {
* current script until the shell is completely idle. Use as
* 'yield Scripting.waitLeisure();'
*/
-function waitLeisure() {
+export function waitLeisure() {
return new Promise(resolve => {
global.run_at_leisure(resolve);
});
}
const PerfHelperIface = loadInterfaceXML('org.gnome.Shell.PerfHelper');
-var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
-function PerfHelper() {
+export const PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
+export function PerfHelper() {
return PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
}
let _perfHelper = null;
-function _getPerfHelper() {
+export function _getPerfHelper() {
if (_perfHelper == null)
_perfHelper = PerfHelper();
return _perfHelper;
}
-function _spawnPerfHelper() {
+export function _spawnPerfHelper() {
let path = Config.LIBEXECDIR;
let command = `${path}/gnome-shell-perf-helper`;
Util.trySpawnCommandLine(command);
}
-function _callRemote(obj, method, ...args) {
+export function _callRemote(obj, method, ...args) {
return new Promise((resolve, reject) => {
args.push((result, excp) => {
if (excp)
@@ -99,18 +103,18 @@ function _callRemote(obj, method, ...args) {
* @param {Object} params: options for window creation.
* {number} [params.width=640] - width of window, in pixels
* {number} [params.height=480] - height of window, in pixels
- * {bool} [params.alpha=false] - whether the window should have an alpha channel
- * {bool} [params.maximized=false] - whether the window should be created maximized
- * {bool} [params.redraws=false] - whether the window should continually redraw itself
+ * {boolean} [params.alpha=false] - whether the window should have an alpha channel
+ * {boolean} [params.maximized=false] - whether the window should be created maximized
+ * {boolean} [params.redraws=false] - whether the window should continually redraw itself
* @returns {Promise}
*
* Creates a window using gnome-shell-perf-helper for testing purposes.
- * While this function can be used with yield in an automation
+ * While this export function can be used with yield in an automation
* script to pause until the D-Bus call to the helper process returns,
* because of the normal X asynchronous mapping process, to actually wait
* until the window has been mapped and exposed, use waitTestWindows().
*/
-function createTestWindow(params = {}) {
+export function createTestWindow(params = {}) {
const {
width = 640,
height = 480,
@@ -132,7 +136,7 @@ function createTestWindow(params = {}) {
* Used within an automation script to pause until all windows previously
* created with createTestWindow have been mapped and exposed.
*/
-function waitTestWindows() {
+export function waitTestWindows() {
let perfHelper = _getPerfHelper();
return _callRemote(perfHelper, perfHelper.WaitWindowsRemote);
}
@@ -142,12 +146,12 @@ function waitTestWindows() {
* @returns {Promise}
*
* Destroys all windows previously created with createTestWindow().
- * While this function can be used with yield in an automation
+ * While this export function can be used with yield in an automation
* script to pause until the D-Bus call to the helper process returns,
* this doesn't guarantee that Mutter has actually finished the destroy
* process because of normal X asynchronicity.
*/
-function destroyTestWindows() {
+export function destroyTestWindows() {
let perfHelper = _getPerfHelper();
return _callRemote(perfHelper, perfHelper.DestroyWindowsRemote);
}
@@ -161,7 +165,7 @@ function destroyTestWindows() {
* within the 'script' namespace that is reserved for events defined locally
* within a performance automation script
*/
-function defineScriptEvent(name, description) {
+export function defineScriptEvent(name, description) {
Shell.PerfLog.get_default().define_event(`script.${name}`,
description,
"");
@@ -174,7 +178,7 @@ function defineScriptEvent(name, description) {
* Convenience function to record a script-local performance event
* previously defined with defineScriptEvent
*/
-function scriptEvent(name) {
+export function scriptEvent(name) {
Shell.PerfLog.get_default().event(`script.${name}`);
}
@@ -183,11 +187,11 @@ function scriptEvent(name) {
*
* Convenience function to trigger statistics collection
*/
-function collectStatistics() {
+export function collectStatistics() {
Shell.PerfLog.get_default().collect_statistics();
}
-function _collect(scriptModule, outputFile) {
+export function _collect(scriptModule, outputFile) {
let eventHandlers = {};
for (let f in scriptModule) {
@@ -282,7 +286,7 @@ function _collect(scriptModule, outputFile) {
}
}
-async function _runPerfScript(scriptModule, outputFile) {
+export async function _runPerfScript(scriptModule, outputFile) {
try {
await scriptModule.run();
} catch (err) {
@@ -340,7 +344,7 @@ async function _runPerfScript(scriptModule, outputFile) {
* After running the script and collecting statistics from the
* event log, GNOME Shell will exit.
**/
-function runPerfScript(scriptModule, outputFile) {
+export function runPerfScript(scriptModule, outputFile) {
Shell.PerfLog.get_default().set_enabled(true);
_spawnPerfHelper();
diff --git a/js/ui/search.js b/js/ui/search.js
index 7300b053e..800fbaed4 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -1,20 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SearchResultsView */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const AppDisplay = imports.ui.appDisplay;
-const IconGrid = imports.ui.iconGrid;
-const Main = imports.ui.main;
-const ParentalControlsManager = imports.misc.parentalControlsManager;
-const RemoteSearch = imports.ui.remoteSearch;
-const Util = imports.misc.util;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as AppDisplay from './appDisplay.js';
+import * as IconGrid from './iconGrid.js';
+import Main from './main.js';
+import * as ParentalControlsManager from '../misc/parentalControlsManager.js';
+import * as RemoteSearch from './remoteSearch.js';
+import * as Util from '../misc/util.js';
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
-var MAX_LIST_SEARCH_RESULTS_ROWS = 5;
+export let MAX_LIST_SEARCH_RESULTS_ROWS = 5;
-var MaxWidthBox = GObject.registerClass(
+export const MaxWidthBox = GObject.registerClass(
class MaxWidthBox extends St.BoxLayout {
vfunc_allocate(box) {
let themeNode = this.get_theme_node();
@@ -32,7 +38,7 @@ class MaxWidthBox extends St.BoxLayout {
}
});
-var SearchResult = GObject.registerClass(
+export const SearchResult = GObject.registerClass(
class SearchResult extends St.Button {
_init(provider, metaInfo, resultsView) {
this.provider = provider;
@@ -61,8 +67,13 @@ class SearchResult extends St.Button {
}
});
-var ListSearchResult = GObject.registerClass(
+export const ListSearchResult = GObject.registerClass(
class ListSearchResult extends SearchResult {
+ /**
+ * @param {*} provider
+ * @param {*} metaInfo
+ * @param {*} resultsView
+ */
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
@@ -132,7 +143,7 @@ class ListSearchResult extends SearchResult {
}
});
-var GridSearchResult = GObject.registerClass(
+export const GridSearchResult = GObject.registerClass(
class GridSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
@@ -152,7 +163,7 @@ class GridSearchResult extends SearchResult {
}
});
-var SearchResultsBase = GObject.registerClass({
+export const SearchResultsBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'focus-child': GObject.ParamSpec.object(
@@ -194,6 +205,24 @@ var SearchResultsBase = GObject.registerClass({
return null;
}
+ _clearResultDisplay() {
+ throw new GObject.NotImplementedError(`_clearResultDisplay in ${this.constructor.name}`);
+ }
+
+ /**
+ * @returns {number}
+ */
+ _getMaxDisplayedResults() {
+ throw new GObject.NotImplementedError(`_getMaxDisplayedResults in ${this.constructor.name}`);
+ }
+
+ /**
+ * @param {*} display
+ */
+ _addItem(display) {
+ throw new GObject.NotImplementedError(`_addItem in ${this.constructor.name}`);
+ }
+
clear() {
this._cancellable.cancel();
for (let resultId in this._resultDisplays)
@@ -293,7 +322,7 @@ var SearchResultsBase = GObject.registerClass({
}
});
-var ListSearchResults = GObject.registerClass(
+export const ListSearchResults = GObject.registerClass(
class ListSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
@@ -348,7 +377,7 @@ class ListSearchResults extends SearchResultsBase {
}
});
-var GridSearchResultsLayout = GObject.registerClass({
+export const GridSearchResultsLayout = GObject.registerClass({
Properties: {
'spacing': GObject.ParamSpec.int('spacing', 'Spacing', 'Spacing',
GObject.ParamFlags.READWRITE, 0, GLib.MAXINT32, 0),
@@ -363,6 +392,9 @@ var GridSearchResultsLayout = GObject.registerClass({
this._container = container;
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
let minWidth = 0;
let natWidth = 0;
@@ -386,6 +418,9 @@ var GridSearchResultsLayout = GObject.registerClass({
return [minWidth, natWidth];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(container, forWidth) {
let minHeight = 0;
let natHeight = 0;
@@ -467,12 +502,12 @@ var GridSearchResultsLayout = GObject.registerClass({
}
});
-var GridSearchResults = GObject.registerClass(
+export const GridSearchResults = GObject.registerClass(
class GridSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
- this._grid = new St.Widget({ style_class: 'grid-search-results' });
+ this._grid = new St.Widget({ style_class: 'grid-search-results', layout_manager: /** @type {GridSearchResultsLayout["prototype"]} */ (null) });
this._grid.layout_manager = new GridSearchResultsLayout();
this._grid.connect('style-changed', () => {
@@ -548,7 +583,7 @@ class GridSearchResults extends SearchResultsBase {
}
});
-var SearchResultsView = GObject.registerClass({
+export const SearchResultsView = GObject.registerClass({
Signals: { 'terms-changed': {} },
}, class SearchResultsView extends St.BoxLayout {
_init() {
@@ -901,7 +936,7 @@ var SearchResultsView = GObject.registerClass({
}
});
-var ProviderInfo = GObject.registerClass(
+export const ProviderInfo = GObject.registerClass(
class ProviderInfo extends St.Button {
_init(provider) {
this.provider = provider;
diff --git a/js/ui/searchController.js b/js/ui/searchController.js
index 5d25897c7..b4decf69e 100644
--- a/js/ui/searchController.js
+++ b/js/ui/searchController.js
@@ -1,13 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SearchController */
-const { Clutter, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const Main = imports.ui.main;
-const Search = imports.ui.search;
-const ShellEntry = imports.ui.shellEntry;
-var FocusTrap = GObject.registerClass(
+import Main from './main.js';
+import * as Search from './search.js';
+import * as ShellEntry from './shellEntry.js';
+
+export const FocusTrap = GObject.registerClass(
class FocusTrap extends St.Widget {
vfunc_navigate_focus(from, direction) {
if (direction === St.DirectionType.TAB_FORWARD ||
@@ -24,7 +27,7 @@ function getTermsForSearchString(searchString) {
return searchString.split(/\s+/);
}
-var SearchController = GObject.registerClass({
+export const SearchController = GObject.registerClass({
Properties: {
'search-active': GObject.ParamSpec.boolean(
'search-active', 'search-active', 'search-active',
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index 96136837a..dd32e9dd0 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -1,15 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SessionMode, listModes */
-const GLib = imports.gi.GLib;
-const Signals = imports.misc.signals;
+import GLib from 'gi://GLib';
+import * as Signals from '../misc/signals.js';
-const FileUtils = imports.misc.fileUtils;
+import * as FileUtils from '../misc/fileUtilsModule.js';
const Config = imports.misc.config;
const DEFAULT_MODE = 'restrictive';
+import { LoginDialog } from "../gdm/loginDialog.js";
+import { UnlockDialog } from "../ui/unlockDialog.js";
+
const _modes = {
'restrictive': {
parentMode: null,
@@ -44,7 +47,7 @@ const _modes = {
hasNotifications: true,
isGreeter: true,
isPrimary: true,
- unlockDialog: imports.gdm.loginDialog.LoginDialog,
+ unlockDialog: LoginDialog,
components: Config.HAVE_NETWORKMANAGER
? ['networkAgent', 'polkitAgent']
: ['polkitAgent'],
@@ -82,7 +85,7 @@ const _modes = {
hasNotifications: true,
isLocked: false,
isPrimary: true,
- unlockDialog: imports.ui.unlockDialog.UnlockDialog,
+ unlockDialog: UnlockDialog,
components: Config.HAVE_NETWORKMANAGER
? ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager']
@@ -125,10 +128,12 @@ function _loadMode(file, info) {
}
function _loadModes() {
+ log('load modes...')
FileUtils.collectFromDatadirs('modes', false, _loadMode);
}
-function listModes() {
+export function listModes() {
+ log('list modes...')
_loadModes();
let loop = new GLib.MainLoop(null, false);
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
@@ -138,12 +143,14 @@ function listModes() {
print(names[i]);
}
loop.quit();
+
+ return false;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] listModes');
loop.run();
}
-var SessionMode = class extends Signals.EventEmitter {
+export class SessionMode extends Signals.EventEmitter {
constructor() {
super();
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index a8070eb92..0a0afd81c 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -1,22 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GnomeShell, ScreenSaverDBus */
-const { Gio, GLib, Meta } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
-const Config = imports.misc.config;
-const ExtensionDownloader = imports.ui.extensionDownloader;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Main = imports.ui.main;
-const Screenshot = imports.ui.screenshot;
-const { loadInterfaceXML } = imports.misc.fileUtils;
-const { DBusSenderChecker } = imports.misc.util;
-const { ControlsState } = imports.ui.overviewControls;
+const Config = imports.misc.config;
+import * as ExtensionDownloader from './extensionDownloader.js';
+import * as ExtensionUtils from '../misc/extensionUtils.js';
+import Main from './main.js';
+import * as Screenshot from './screenshot.js';
+import { ControlsState } from './overviewControls.js';
+import { DBusSenderChecker } from '../misc/util.js';
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell');
const ScreenSaverIface = loadInterfaceXML('org.gnome.ScreenSaver');
-var GnomeShell = class {
+export class GnomeShell {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
@@ -39,9 +41,9 @@ var GnomeShell = class {
this._cachedOverviewVisible = false;
Main.overview.connect('showing',
- this._checkOverviewVisibleChanged.bind(this));
+ this._checkOverviewVisibleChanged.bind(this));
Main.overview.connect('hidden',
- this._checkOverviewVisibleChanged.bind(this));
+ this._checkOverviewVisibleChanged.bind(this));
}
/**
@@ -116,10 +118,10 @@ var GnomeShell = class {
params[param] = params[param].deep_unpack();
let { connector,
- label,
- level,
- max_level: maxLevel,
- icon: serializedIcon } = params;
+ label,
+ level,
+ max_level: maxLevel,
+ icon: serializedIcon } = params;
let monitorIndex = -1;
if (connector) {
@@ -233,7 +235,7 @@ var GnomeShell = class {
let ungrabSucceeded = true;
for (let i = 0; i < actions.length; i++)
- ungrabSucceeded &= this._ungrabAcceleratorForSender(actions[i], sender);
+ ungrabSucceeded = ungrabSucceeded && this._ungrabAcceleratorForSender(actions[i], sender);
invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
}
@@ -274,7 +276,7 @@ var GnomeShell = class {
if (!this._grabbers.has(sender)) {
let id = Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
- this._onGrabberBusNameVanished.bind(this));
+ this._onGrabberBusNameVanished.bind(this));
this._grabbers.set(sender, id);
}
@@ -363,7 +365,7 @@ var GnomeShell = class {
const GnomeShellExtensionsIface = loadInterfaceXML('org.gnome.Shell.Extensions');
-var GnomeShellExtensions = class {
+export class GnomeShellExtensions {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
@@ -378,8 +380,8 @@ var GnomeShellExtensions = class {
new GLib.Variant('b', this._userExtensionsEnabled));
});
- Main.extensionManager.connect('extension-state-changed',
- this._extensionStateChanged.bind(this));
+ // Main.extensionManager.connect('extension-state-changed',
+ // this._extensionStateChanged.bind(this));
}
ListExtensions() {
@@ -460,11 +462,11 @@ var GnomeShellExtensions = class {
new GLib.Variant('(sa{sv})', [newState.uuid, state]));
this._dbusImpl.emit_signal('ExtensionStatusChanged',
- GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
+ GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
}
};
-var ScreenSaverDBus = class {
+export class ScreenSaverDBus {
constructor(screenShield) {
this._screenShield = screenShield;
screenShield.connect('active-changed', shield => {
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index f3e2b63d3..56a40f210 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -1,13 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addContextMenu CapsLockWarning */
-const { Clutter, GObject, Pango, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const BoxPointer = imports.ui.boxpointer;
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
-var EntryMenu = class extends PopupMenu.PopupMenu {
+import * as BoxPointer from './boxpointer.js';
+import Main from './main.js';
+import * as PopupMenu from './popupMenu.js';
+
+export class EntryMenu extends PopupMenu.PopupMenu {
constructor(entry) {
super(entry, 0, St.Side.TOP);
@@ -126,7 +131,7 @@ function _onPopup(actor, entry) {
entry.menu.open(BoxPointer.PopupAnimation.FULL);
}
-function addContextMenu(entry, params = {}) {
+export function addContextMenu(entry, params = {}) {
if (entry.menu)
return;
@@ -156,7 +161,7 @@ function addContextMenu(entry, params = {}) {
});
}
-var CapsLockWarning = GObject.registerClass(
+export const CapsLockWarning = GObject.registerClass(
class CapsLockWarning extends St.Label {
_init(params) {
let defaultParams = { style_class: 'caps-lock-warning-label' };
diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js
index 1101c03b3..0d8bde59e 100644
--- a/js/ui/shellMountOperation.js
+++ b/js/ui/shellMountOperation.js
@@ -1,21 +1,28 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ShellMountOperation, GnomeShellMountOpHandler */
-const { Clutter, Gio, GLib, GObject, Pango, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Animation = imports.ui.animation;
-const CheckBox = imports.ui.checkBox;
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const ModalDialog = imports.ui.modalDialog;
-const ShellEntry = imports.ui.shellEntry;
-const { loadInterfaceXML } = imports.misc.fileUtils;
-const Util = imports.misc.util;
+import * as Animation from './animation.js';
+import * as CheckBox from './checkBox.js';
+import * as Dialog from './dialog.js';
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
+import * as ModalDialog from './modalDialog.js';
+import * as ShellEntry from './shellEntry.js';
-var LIST_ITEM_ICON_SIZE = 48;
-var WORK_SPINNER_ICON_SIZE = 16;
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
+import * as Util from '../misc/util.js';
+
+export let LIST_ITEM_ICON_SIZE = 48;
+export let WORK_SPINNER_ICON_SIZE = 16;
const REMEMBER_MOUNT_PASSWORD_KEY = 'remember-mount-password';
@@ -48,7 +55,7 @@ function _setLabelsForMessage(content, message) {
/* -------------------------------------------------------- */
-var ShellMountOperation = class {
+export class ShellMountOperation {
constructor(source, params = {}) {
const { existingDialog = null } = params;
@@ -186,7 +193,7 @@ var ShellMountOperation = class {
}
};
-var ShellUnmountNotifier = GObject.registerClass(
+export const ShellUnmountNotifier = GObject.registerClass(
class ShellUnmountNotifier extends MessageTray.Source {
_init() {
super._init('', 'media-removable');
@@ -224,7 +231,7 @@ class ShellUnmountNotifier extends MessageTray.Source {
}
});
-var ShellMountQuestionDialog = GObject.registerClass({
+export const ShellMountQuestionDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_INT] } },
}, class ShellMountQuestionDialog extends ModalDialog.ModalDialog {
_init() {
@@ -252,7 +259,7 @@ var ShellMountQuestionDialog = GObject.registerClass({
}
});
-var ShellMountPasswordDialog = GObject.registerClass({
+export const ShellMountPasswordDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_INT,
GObject.TYPE_STRING,
GObject.TYPE_BOOLEAN,
@@ -415,9 +422,10 @@ var ShellMountPasswordDialog = GObject.registerClass({
_onEntryActivate() {
let pim = 0;
if (this._pimEntry !== null) {
- pim = this._pimEntry.get_text();
+ // FIXME
+ let pim_text = this._pimEntry.get_text();
- if (isNaN(pim)) {
+ if (Number.isNaN(Number.parseInt(pim_text))) {
this._pimEntry.set_text('');
this._errorMessageLabel.text = _('The PIM must be a number or empty.');
this._errorMessageLabel.opacity = 255;
@@ -439,7 +447,7 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._hiddenVolume.checked,
this._systemVolume &&
this._systemVolume.checked,
- parseInt(pim));
+ Number.parseInt(pim.toFixed(0)));
}
_onKeyfilesCheckboxClicked() {
@@ -469,7 +477,7 @@ var ShellMountPasswordDialog = GObject.registerClass({
}
});
-var ShellProcessesDialog = GObject.registerClass({
+export const ShellProcessesDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_INT] } },
}, class ShellProcessesDialog extends ModalDialog.ModalDialog {
_init() {
@@ -526,14 +534,15 @@ var ShellProcessesDialog = GObject.registerClass({
const GnomeShellMountOpIface = loadInterfaceXML('org.Gtk.MountOperationHandler');
-var ShellMountOperationType = {
+/** @enum {number} */
+export const ShellMountOperationType = {
NONE: 0,
ASK_PASSWORD: 1,
ASK_QUESTION: 2,
SHOW_PROCESSES: 3,
};
-var GnomeShellMountOpHandler = class {
+export class GnomeShellMountOpHandler {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellMountOpIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/MountOperationHandler');
@@ -613,7 +622,7 @@ var GnomeShellMountOpHandler = class {
AskPasswordAsync(params, invocation) {
let [id, message, iconName_, defaultUser_, defaultDomain_, flags] = params;
- if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_PASSWORD)) {
+ if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_PASSWORD) && this._dialog instanceof ShellMountPasswordDialog) {
this._dialog.reaskPassword();
return;
}
@@ -663,14 +672,15 @@ var GnomeShellMountOpHandler = class {
AskQuestionAsync(params, invocation) {
let [id, message, iconName_, choices] = params;
- if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_QUESTION)) {
+ if (this._setCurrentRequest(invocation, id, ShellMountOperationType.ASK_QUESTION) && this._dialog instanceof ShellMountQuestionDialog) {
this._dialog.update(message, choices);
return;
}
this._closeDialog();
- this._dialog = new ShellMountQuestionDialog(message);
+ // FIXME
+ this._dialog = new ShellMountQuestionDialog();
this._dialog.connect('response', (object, choice) => {
let response;
let details = {};
@@ -710,7 +720,7 @@ var GnomeShellMountOpHandler = class {
ShowProcessesAsync(params, invocation) {
let [id, message, iconName_, applicationPids, choices] = params;
- if (this._setCurrentRequest(invocation, id, ShellMountOperationType.SHOW_PROCESSES)) {
+ if (this._setCurrentRequest(invocation, id, ShellMountOperationType.SHOW_PROCESSES) && this._dialog instanceof ShellProcessesDialog) {
this._dialog.update(message, applicationPids, choices);
return;
}
diff --git a/js/ui/slider.js b/js/ui/slider.js
index ba3a233f1..7216b0d0e 100644
--- a/js/ui/slider.js
+++ b/js/ui/slider.js
@@ -1,13 +1,16 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported Slider */
-const { Atk, Clutter, GObject } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
-const BarLevel = imports.ui.barLevel;
-var SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */
+import * as BarLevel from './barLevel.js';
-var Slider = GObject.registerClass({
+export let SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */
+
+export const Slider = GObject.registerClass({
Signals: {
'drag-begin': {},
'drag-end': {},
diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js
index a0513f68c..844acbc8b 100644
--- a/js/ui/status/accessibility.js
+++ b/js/ui/status/accessibility.js
@@ -1,10 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ATIndicator */
-const { Gio, GLib, GObject, St } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
const A11Y_SCHEMA = 'org.gnome.desktop.a11y';
const KEY_ALWAYS_SHOW = 'always-show-universal-access-status';
@@ -29,7 +33,7 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
const HIGH_CONTRAST_THEME = 'HighContrast';
-var ATIndicator = GObject.registerClass(
+export const ATIndicator = GObject.registerClass(
class ATIndicator extends PanelMenu.Button {
_init() {
super._init(0.5, _("Accessibility"));
@@ -97,6 +101,12 @@ class ATIndicator extends PanelMenu.Button {
GLib.Source.set_name_by_id(this._syncMenuVisibilityIdle, '[gnome-shell] this._syncMenuVisibility');
}
+ /**
+ * @param {string} string
+ * @param {boolean} initialValue
+ * @param {boolean} writable
+ * @param {(state: boolean) => void} onSet
+ */
_buildItemExtended(string, initialValue, writable, onSet) {
let widget = new PopupMenu.PopupSwitchMenuItem(string, initialValue);
if (!writable) {
diff --git a/js/ui/status/bluetooth.js b/js/ui/status/bluetooth.js
index d4db93ea7..85c240a9b 100644
--- a/js/ui/status/bluetooth.js
+++ b/js/ui/status/bluetooth.js
@@ -1,13 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Gio, GLib, GnomeBluetooth, GObject } = imports.gi;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GnomeBluetooth from 'gi://GnomeBluetooth';
+import GObject from 'gi://GObject';
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
+
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
@@ -17,7 +21,7 @@ const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface
const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup';
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
@@ -73,10 +77,10 @@ class Indicator extends PanelMenu.SystemIndicator {
_getDefaultAdapter() {
let [ret, iter] = this._model.get_iter_first();
while (ret) {
- let isDefault = this._model.get_value(iter,
- GnomeBluetooth.Column.DEFAULT);
- let isPowered = this._model.get_value(iter,
- GnomeBluetooth.Column.POWERED);
+ /** @type {boolean} */
+ let isDefault = (this._model.get_value(iter, GnomeBluetooth.Column.DEFAULT));
+ /** @type {boolean} */
+ let isPowered = (this._model.get_value(iter, GnomeBluetooth.Column.POWERED));
if (isDefault && isPowered)
return iter;
ret = this._model.iter_next(iter);
@@ -91,17 +95,19 @@ class Indicator extends PanelMenu.SystemIndicator {
let deviceInfos = [];
let [ret, iter] = this._model.iter_children(adapter);
while (ret) {
- const isPaired = this._model.get_value(iter,
- GnomeBluetooth.Column.PAIRED);
- const isTrusted = this._model.get_value(iter,
- GnomeBluetooth.Column.TRUSTED);
+ /** @type {boolean} */
+ const isPaired = (this._model.get_value(iter,
+ GnomeBluetooth.Column.PAIRED));
+ /** @type {boolean} */
+ const isTrusted = (this._model.get_value(iter,
+ GnomeBluetooth.Column.TRUSTED));
if (isPaired || isTrusted) {
deviceInfos.push({
- connected: this._model.get_value(iter,
- GnomeBluetooth.Column.CONNECTED),
- name: this._model.get_value(iter,
- GnomeBluetooth.Column.ALIAS),
+ connected: /** @type {boolean} */ (this._model.get_value(iter,
+ GnomeBluetooth.Column.CONNECTED)),
+ name: /** @type {string} */ (this._model.get_value(iter,
+ GnomeBluetooth.Column.ALIAS)),
});
}
diff --git a/js/ui/status/brightness.js b/js/ui/status/brightness.js
index 2a27e7844..292dcfaac 100644
--- a/js/ui/status/brightness.js
+++ b/js/ui/status/brightness.js
@@ -1,13 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Gio, GObject, St } = imports.gi;
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
-const Slider = imports.ui.slider;
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
+import * as Slider from '../slider.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
@@ -15,7 +17,7 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen');
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/dwellClick.js b/js/ui/status/dwellClick.js
index 4b1d8a2c1..a3c35fafc 100644
--- a/js/ui/status/dwellClick.js
+++ b/js/ui/status/dwellClick.js
@@ -1,7 +1,11 @@
/* exported DwellClickIndicator */
-const { Clutter, Gio, GLib, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-const PanelMenu = imports.ui.panelMenu;
+import * as PanelMenu from '../panelMenu.js';
const MOUSE_A11Y_SCHEMA = 'org.gnome.desktop.a11y.mouse';
const KEY_DWELL_CLICK_ENABLED = 'dwell-click-enabled';
@@ -30,7 +34,7 @@ const DWELL_CLICK_MODES = {
},
};
-var DwellClickIndicator = GObject.registerClass(
+export const DwellClickIndicator = GObject.registerClass(
class DwellClickIndicator extends PanelMenu.Button {
_init() {
super._init(0.5, _("Dwell Click"));
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 80a91bdfa..c8ac086e0 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -1,22 +1,35 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputSourceIndicator */
-const { Clutter, Gio, GLib, GObject, IBus, Meta, Shell, St } = imports.gi;
-const Gettext = imports.gettext;
-const Signals = imports.misc.signals;
-
-const IBusManager = imports.misc.ibusManager;
-const KeyboardManager = imports.misc.keyboardManager;
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
-const PanelMenu = imports.ui.panelMenu;
-const SwitcherPopup = imports.ui.switcherPopup;
-const Util = imports.misc.util;
-
-var INPUT_SOURCE_TYPE_XKB = 'xkb';
-var INPUT_SOURCE_TYPE_IBUS = 'ibus';
-
-var LayoutMenuItem = GObject.registerClass(
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import IBus from 'gi://IBus';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as Gettext from 'gettext';
+import * as Signals from '../../misc/signals.js';
+
+import * as IBusManager from '../../misc/ibusManager.js';
+import * as KeyboardManager from '../../misc/keyboardManager.js';
+import Main from '../main.js';
+import * as PopupMenu from '../popupMenu.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as SwitcherPopup from '../switcherPopup.js';
+import * as Util from '../../misc/util.js';
+
+export let INPUT_SOURCE_TYPE_XKB = 'xkb';
+export let INPUT_SOURCE_TYPE_IBUS = 'ibus';
+
+/**
+ * @typedef {object} LayoutMenuItemParams
+ * @property {string} displayName
+ * @property {string} shortName
+ */
+
+export const LayoutMenuItem = GObject.registerClass(
class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(displayName, shortName) {
super._init();
@@ -32,7 +45,7 @@ class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {
}
});
-var InputSource = class extends Signals.EventEmitter {
+export class InputSource extends Signals.EventEmitter {
constructor(type, id, displayName, shortName, index) {
super();
@@ -72,8 +85,13 @@ var InputSource = class extends Signals.EventEmitter {
}
};
-var InputSourcePopup = GObject.registerClass(
+export const InputSourcePopup = GObject.registerClass(
class InputSourcePopup extends SwitcherPopup.SwitcherPopup {
+ /**
+ * @param {*} items
+ * @param {*} action
+ * @param {*} actionBackward
+ */
_init(items, action, actionBackward) {
super._init(items);
@@ -105,10 +123,13 @@ class InputSourcePopup extends SwitcherPopup.SwitcherPopup {
}
});
-var InputSourceSwitcher = GObject.registerClass(
+export const InputSourceSwitcher = GObject.registerClass(
class InputSourceSwitcher extends SwitcherPopup.SwitcherList {
+ /**
+ * @param {*} items
+ */
_init(items) {
- super._init(true);
+ super._init({ squareItems: true });
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
@@ -136,7 +157,7 @@ class InputSourceSwitcher extends SwitcherPopup.SwitcherList {
}
});
-var InputSourceSettings = class extends Signals.EventEmitter {
+export class InputSourceSettings extends Signals.EventEmitter {
constructor() {
super();
@@ -177,7 +198,7 @@ var InputSourceSettings = class extends Signals.EventEmitter {
}
};
-var InputSourceSystemSettings = class extends InputSourceSettings {
+export class InputSourceSystemSettings extends InputSourceSettings {
constructor() {
super();
@@ -202,6 +223,7 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
}
async _reload() {
+ /** @type {{ [key: string]: GLib.Variant }} */
let props;
try {
const result = await Gio.DBus.system.call(
@@ -211,15 +233,19 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null);
- [props] = result.deep_unpack();
+ /** @type {[{ [key: string]: GLib.Variant }]} */
+ [props] = (result.deep_unpack());
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
- const layouts = props['X11Layout'].unpack();
- const variants = props['X11Variant'].unpack();
- const options = props['X11Options'].unpack();
+ /** @type {string} */
+ const layouts = (props['X11Layout'].unpack());
+ /** @type {string} */
+ const variants = (props['X11Variant'].unpack());
+ /** @type {string} */
+ const options = (props['X11Options'].unpack());
if (layouts !== this._layouts ||
variants !== this._variants) {
@@ -252,7 +278,7 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
}
};
-var InputSourceSessionSettings = class extends InputSourceSettings {
+export class InputSourceSessionSettings extends InputSourceSettings {
constructor() {
super();
@@ -269,12 +295,14 @@ var InputSourceSessionSettings = class extends InputSourceSettings {
}
_getSourcesList(key) {
+ /** @type {{ type: string, id: number }[]} */
let sourcesList = [];
let sources = this._settings.get_value(key);
let nSources = sources.n_children();
for (let i = 0; i < nSources; i++) {
- let [type, id] = sources.get_child_value(i).deep_unpack();
+ /** @type {[string, number]} */
+ let [type, id] = (sources.get_child_value(i).deep_unpack());
sourcesList.push({ type, id });
}
return sourcesList;
@@ -289,7 +317,8 @@ var InputSourceSessionSettings = class extends InputSourceSettings {
}
set mruSources(sourcesList) {
- let sources = GLib.Variant.new('a(ss)', sourcesList);
+ let list = sourcesList.map(/** @returns {[string, string]} */ ({type, id}) => [type, id.toFixed(0)]);
+ let sources = GLib.Variant.new('a(ss)', list);
this._settings.set_value(this._KEY_MRU_SOURCES, sources);
}
@@ -302,7 +331,7 @@ var InputSourceSessionSettings = class extends InputSourceSettings {
}
};
-var InputSourceManager = class extends Signals.EventEmitter {
+export class InputSourceManager extends Signals.EventEmitter {
constructor() {
super();
@@ -782,16 +811,20 @@ var InputSourceManager = class extends Signals.EventEmitter {
}
};
+/** @type {InputSourceManager | null} */
let _inputSourceManager = null;
-function getInputSourceManager() {
+export function getInputSourceManager() {
if (_inputSourceManager == null)
_inputSourceManager = new InputSourceManager();
return _inputSourceManager;
}
-var InputSourceIndicatorContainer = GObject.registerClass(
+export const InputSourceIndicatorContainer = GObject.registerClass(
class InputSourceIndicatorContainer extends St.Widget {
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(forHeight) {
// Here, and in vfunc_get_preferred_height, we need to query
// for the height of all children, but we ignore the results
@@ -803,6 +836,9 @@ class InputSourceIndicatorContainer extends St.Widget {
}, [0, 0]);
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(forWidth) {
return this.get_children().reduce((maxHeight, child) => {
let height = child.get_preferred_height(forWidth);
@@ -826,7 +862,7 @@ class InputSourceIndicatorContainer extends St.Widget {
}
});
-var InputSourceIndicator = GObject.registerClass(
+export const InputSourceIndicator = GObject.registerClass(
class InputSourceIndicator extends PanelMenu.Button {
_init() {
super._init(0.5, _("Keyboard"));
diff --git a/js/ui/status/location.js b/js/ui/status/location.js
index 6b399793c..c672da6dc 100644
--- a/js/ui/status/location.js
+++ b/js/ui/status/location.js
@@ -1,16 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
-
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
-const ModalDialog = imports.ui.modalDialog;
-const PermissionStore = imports.misc.permissionStore;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+import * as Dialog from '../dialog.js';
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
+import * as ModalDialog from '../modalDialog.js';
+import * as PermissionStore from '../../misc/permissionStore.js';
+
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const LOCATION_SCHEMA = 'org.gnome.system.location';
const MAX_ACCURACY_LEVEL = 'max-accuracy-level';
@@ -19,7 +24,8 @@ const ENABLED = 'enabled';
const APP_PERMISSIONS_TABLE = 'location';
const APP_PERMISSIONS_ID = 'location';
-var GeoclueAccuracyLevel = {
+/** @enum {number} */
+export const GeoclueAccuracyLevel = {
NONE: 0,
COUNTRY: 1,
CITY: 4,
@@ -37,10 +43,10 @@ function accuracyLevelToString(accuracyLevel) {
return 'NONE';
}
-var GeoclueIface = loadInterfaceXML('org.freedesktop.GeoClue2.Manager');
+export const GeoclueIface = loadInterfaceXML('org.freedesktop.GeoClue2.Manager');
const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
-var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
+export const AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
let _geoclueAgent = null;
function _getGeoclueAgent() {
@@ -210,7 +216,7 @@ var GeoclueAgent = GObject.registerClass({
}
});
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
@@ -373,7 +379,8 @@ var AppAuthorizer = class {
let dateStr = Math.round(Date.now() / 1000).toString();
this._permissions[this.desktopId] = [levelStr, dateStr];
- let data = GLib.Variant.new('av', {});
+ // FIXME
+ let data = GLib.Variant.new('av', []);
this._permStoreProxy.SetRemote(APP_PERMISSIONS_TABLE,
true,
@@ -387,7 +394,7 @@ var AppAuthorizer = class {
}
};
-var GeolocationDialog = GObject.registerClass({
+export const GeolocationDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_UINT] } },
}, class GeolocationDialog extends ModalDialog.ModalDialog {
_init(name, reason, reqAccuracyLevel) {
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 890f9a456..416cbb159 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -1,25 +1,33 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NMApplet */
-const { Clutter, Gio, GLib, GObject, Meta, NM, Polkit, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const Animation = imports.ui.animation;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
-const MessageTray = imports.ui.messageTray;
-const ModalDialog = imports.ui.modalDialog;
-const ModemManager = imports.misc.modemManager;
-const Rfkill = imports.ui.status.rfkill;
-const Util = imports.misc.util;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import NM from 'gi://NM';
+import St from 'gi://St';
+import Polkit from 'gi://Polkit';
+import Meta from 'gi://Meta';
+import * as Signals from '../../misc/signals.js';
+
+import * as Animation from '../animation.js';
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
+import * as MessageTray from '../messageTray.js';
+import * as ModalDialog from '../modalDialog.js';
+import * as ModemManager from '../../misc/modemManager.js';
+import * as Rfkill from './rfkill.js';
+import * as Util from '../../misc/util.js';
+
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
Gio._promisify(NM.Client, 'new_async', 'new_finish');
Gio._promisify(NM.Client.prototype,
'check_connectivity_async', 'check_connectivity_finish');
+/** @enum {string} */
const NMConnectionCategory = {
INVALID: 'invalid',
WIRED: 'wired',
@@ -28,6 +36,7 @@ const NMConnectionCategory = {
VPN: 'vpn',
};
+/** @enum {number} */
const NMAccessPointSecurity = {
NONE: 1,
WEP: 2,
@@ -37,14 +46,15 @@ const NMAccessPointSecurity = {
WPA2_ENT: 6,
};
-var MAX_DEVICE_ITEMS = 4;
+export let MAX_DEVICE_ITEMS = 4;
// small optimization, to avoid using [] all the time
const NM80211Mode = NM['80211Mode'];
const NM80211ApFlags = NM['80211ApFlags'];
const NM80211ApSecurityFlags = NM['80211ApSecurityFlags'];
-var PortalHelperResult = {
+/** @enum {number} */
+export const PortalHelperResult = {
CANCELLED: 0,
COMPLETED: 1,
RECHECK: 2,
@@ -73,6 +83,9 @@ function ssidToLabel(ssid) {
return label;
}
+/**
+ * @param {NM.ActiveConnection} active
+ */
function ensureActiveConnectionProps(active) {
if (!active._primaryDevice) {
let devices = active.get_devices();
@@ -89,7 +102,7 @@ function launchSettingsPanel(panel, ...args) {
[panel, args.map(s => new GLib.Variant('s', s))]);
const platformData = {
'desktop-startup-id': new GLib.Variant('s',
- '_TIME%s'.format(global.get_current_time())),
+ '_TIME%s'.format(global.get_current_time().toFixed(0))),
};
try {
Gio.DBus.session.call(
@@ -108,7 +121,7 @@ function launchSettingsPanel(panel, ...args) {
}
}
-var NMConnectionItem = class extends Signals.EventEmitter {
+export class NMConnectionItem extends Signals.EventEmitter {
constructor(section, connection) {
super();
@@ -200,14 +213,14 @@ var NMConnectionItem = class extends Signals.EventEmitter {
if (this._activeConnection) {
this._activeConnectionChangedId = this._activeConnection.connect('notify::state',
- this._connectionStateChanged.bind(this));
+ this._connectionStateChanged.bind(this));
}
this._sync();
}
};
-var NMConnectionSection = class NMConnectionSection extends Signals.EventEmitter {
+export class NMConnectionSection extends Signals.EventEmitter {
constructor(client) {
super();
@@ -253,10 +266,27 @@ var NMConnectionSection = class NMConnectionSection extends Signals.EventEmitter
this.item.icon.icon_name = this._getMenuIcon();
}
+ /**
+ * @return {string}
+ */
+ _getStatus() {
+ throw new GObject.NotImplementedError(`_getStatus in ${this.constructor.name}`);
+ }
+
+ /**
+ * @return {string}
+ */
+ getIndicatorIcon() {
+ throw new GObject.NotImplementedError(`getIndicatorIcon in ${this.constructor.name}`);
+ }
+
_getMenuIcon() {
return this.getIndicatorIcon();
}
+ /**
+ * @returns {string}
+ */
getConnectLabel() {
return _("Connect");
}
@@ -338,7 +368,12 @@ var NMConnectionSection = class NMConnectionSection extends Signals.EventEmitter
}
};
-var NMConnectionDevice = class NMConnectionDevice extends NMConnectionSection {
+
+export class NMConnectionDevice extends NMConnectionSection {
+ /**
+ * @param {NM.Client} client
+ * @param {NM.Device} device
+ */
constructor(client, device) {
super(client);
@@ -498,7 +533,11 @@ var NMConnectionDevice = class NMConnectionDevice extends NMConnectionSection {
}
};
-var NMDeviceWired = class extends NMConnectionDevice {
+export class NMDeviceWired extends NMConnectionDevice {
+ /**
+ * @param {NM.Client} client
+ * @param {NM.Device} device
+ */
constructor(client, device) {
super(client, device);
@@ -541,7 +580,11 @@ var NMDeviceWired = class extends NMConnectionDevice {
}
};
-var NMDeviceModem = class extends NMConnectionDevice {
+export class NMDeviceModem extends NMConnectionDevice {
+ /**
+ * @param {NM.Client} client
+ * @param {NM.DeviceModem} device
+ */
constructor(client, device) {
super(client, device);
@@ -647,10 +690,16 @@ var NMDeviceModem = class extends NMConnectionDevice {
}
};
-var NMDeviceBluetooth = class extends NMConnectionDevice {
+export class NMDeviceBluetooth extends NMConnectionDevice {
+ /**
+ * @param {NM.Client} client
+ * @param {NM.DeviceBt} device
+ */
constructor(client, device) {
super(client, device);
+ this._device = device;
+
this.item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-network-panel.desktop');
}
@@ -681,7 +730,7 @@ var NMDeviceBluetooth = class extends NMConnectionDevice {
}
};
-var NMWirelessDialogItem = GObject.registerClass({
+export const NMWirelessDialogItem = GObject.registerClass({
Signals: {
'selected': {},
},
@@ -708,7 +757,7 @@ var NMWirelessDialogItem = GObject.registerClass({
this.add_child(this._label);
this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon',
- icon_name: 'object-select-symbolic' });
+ icon_name: 'object-select-symbolic' })
this.add(this._selectedIcon);
this._icons = new St.BoxLayout({
@@ -755,7 +804,7 @@ var NMWirelessDialogItem = GObject.registerClass({
}
});
-var NMWirelessDialog = GObject.registerClass(
+export const NMWirelessDialog = GObject.registerClass(
class NMWirelessDialog extends ModalDialog.ModalDialog {
_init(client, device) {
super._init({ styleClass: 'nm-dialog' });
@@ -1155,15 +1204,16 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._resortItems();
} else {
+ const ssid = accessPoint.get_ssid();
network = {
- ssid: accessPoint.get_ssid(),
+ ssid: ssid,
+ ssidText: ssidToLabel(ssid),
mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint),
connections: [],
item: null,
accessPoints: [accessPoint],
};
- network.ssidText = ssidToLabel(network.ssid);
this._checkConnections(network, accessPoint);
let newPos = Util.insertSorted(this._networks, network, this._networkSortFunction);
@@ -1258,7 +1308,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
}
});
-var NMDeviceWireless = class extends Signals.EventEmitter {
+export class NMDeviceWireless extends Signals.EventEmitter {
constructor(client, device) {
super();
@@ -1471,7 +1521,7 @@ var NMDeviceWireless = class extends Signals.EventEmitter {
}
};
-var NMVpnConnectionItem = class extends NMConnectionItem {
+export class NMVpnConnectionItem extends NMConnectionItem {
isActive() {
if (this._activeConnection == null)
return false;
@@ -1490,6 +1540,9 @@ var NMVpnConnectionItem = class extends NMConnectionItem {
_sync() {
let isActive = this.isActive();
this.labelItem.label.text = isActive ? _("Turn Off") : this._section.getConnectLabel();
+
+ assertType(this.radioItem, PopupMenu.PopupSwitchMenuItem);
+
this.radioItem.setToggleState(isActive);
this.radioItem.setStatus(this._getStatus());
this.emit('icon-changed');
@@ -1558,7 +1611,7 @@ var NMVpnConnectionItem = class extends NMConnectionItem {
}
};
-var NMVpnSection = class extends NMConnectionSection {
+export class NMVpnSection extends NMConnectionSection {
constructor(client) {
super(client);
@@ -1632,7 +1685,7 @@ var NMVpnSection = class extends NMConnectionSection {
}
};
-var DeviceCategory = class extends PopupMenu.PopupMenuSection {
+class DeviceCategory extends PopupMenu.PopupMenuSection {
constructor(category) {
super();
@@ -1693,7 +1746,7 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection {
}
};
-var NMApplet = GObject.registerClass(
+export const NMApplet = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
@@ -1803,7 +1856,7 @@ class Indicator extends PanelMenu.SystemIndicator {
try {
this._deviceAdded(this._client, devices[i], true);
} catch (e) {
- log('Failed to add device %s: %s'.format(devices[i], e.toString()));
+ log('Failed to add device %s: %s'.format(devices[i].toString(), e.toString()));
}
}
this._syncDeviceNames();
diff --git a/js/ui/status/nightLight.js b/js/ui/status/nightLight.js
index 7fcbfe5c2..f98b5ab2a 100644
--- a/js/ui/status/nightLight.js
+++ b/js/ui/status/nightLight.js
@@ -1,13 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Gio, GObject } = imports.gi;
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'org.gnome.SettingsDaemon.Color';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color';
@@ -15,7 +16,7 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color';
const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color');
const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface);
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/power.js b/js/ui/status/power.js
index ed6a46a63..ae5d9f9f7 100644
--- a/js/ui/status/power.js
+++ b/js/ui/status/power.js
@@ -1,13 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
+import UPower from 'gi://UPowerGlib';
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'org.freedesktop.UPower';
const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
@@ -17,7 +21,7 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface)
const SHOW_BATTERY_PERCENTAGE = 'show-battery-percentage';
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/powerProfiles.js b/js/ui/status/powerProfiles.js
index 61205bbc6..649b7ebfc 100644
--- a/js/ui/status/powerProfiles.js
+++ b/js/ui/status/powerProfiles.js
@@ -3,11 +3,11 @@
const { Gio, GObject } = imports.gi;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'net.hadess.PowerProfiles';
const OBJECT_PATH = '/net/hadess/PowerProfiles';
@@ -26,7 +26,7 @@ const PROFILE_ICONS = {
'power-saver': 'power-profile-power-saver-symbolic',
};
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/remoteAccess.js b/js/ui/status/remoteAccess.js
index 21f6581b6..18d41acc9 100644
--- a/js/ui/status/remoteAccess.js
+++ b/js/ui/status/remoteAccess.js
@@ -1,12 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported RemoteAccessApplet */
-const { GObject, Meta } = imports.gi;
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-var RemoteAccessApplet = GObject.registerClass(
+export const RemoteAccessApplet = GObject.registerClass(
class RemoteAccessApplet extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/rfkill.js b/js/ui/status/rfkill.js
index c090ffd00..d296c71f1 100644
--- a/js/ui/status/rfkill.js
+++ b/js/ui/status/rfkill.js
@@ -1,14 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Gio, GObject } = imports.gi;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import * as Signals from '../../misc/signals.js';
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
@@ -54,7 +55,7 @@ var RfkillManager = class extends Signals.EventEmitter {
};
var _manager;
-function getRfkillManager() {
+export function getRfkillManager() {
if (_manager != null)
return _manager;
@@ -62,7 +63,7 @@ function getRfkillManager() {
return _manager;
}
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/system.js b/js/ui/status/system.js
index 6f71109c5..7c2547753 100644
--- a/js/ui/status/system.js
+++ b/js/ui/status/system.js
@@ -1,21 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { GObject, Shell, St } = imports.gi;
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const BoxPointer = imports.ui.boxpointer;
-const SystemActions = imports.misc.systemActions;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+import * as BoxPointer from '../boxpointer.js';
+import * as SystemActions from '../../misc/systemActions.js';
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
- this._systemActions = new SystemActions.getDefault();
+ this._systemActions = SystemActions.getDefault();
this._createSubMenu();
diff --git a/js/ui/status/thunderbolt.js b/js/ui/status/thunderbolt.js
index 12535394e..c0176efa6 100644
--- a/js/ui/status/thunderbolt.js
+++ b/js/ui/status/thunderbolt.js
@@ -3,14 +3,18 @@
// the following is a modified version of bolt/contrib/js/client.js
-const { Gio, GLib, GObject, Polkit, Shell } = imports.gi;
-const Signals = imports.misc.signals;
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Polkit from 'gi://Polkit';
+import Shell from 'gi://Shell';
+import * as Signals from '../../misc/signals.js';
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const PanelMenu = imports.ui.panelMenu;
+import Main from '../main.js';
+import * as MessageTray from '../messageTray.js';
+import * as PanelMenu from '../panelMenu.js';
-const { loadInterfaceXML } = imports.misc.fileUtils;
+import { loadInterfaceXML } from '../../misc/fileUtilsModule.js';
/* Keep in sync with data/org.freedesktop.bolt.xml */
@@ -21,7 +25,7 @@ const BoltDeviceProxy = Gio.DBusProxy.makeProxyWrapper(BoltDeviceInterface);
/* */
-var Status = {
+export const Status = {
DISCONNECTED: 'disconnected',
CONNECTING: 'connecting',
CONNECTED: 'connected',
@@ -30,17 +34,17 @@ var Status = {
AUTHORIZED: 'authorized',
};
-var Policy = {
+export const Policy = {
DEFAULT: 'default',
MANUAL: 'manual',
AUTO: 'auto',
};
-var AuthCtrl = {
+export const AuthCtrl = {
NONE: 'none',
};
-var AuthMode = {
+export const AuthMode = {
DISABLED: 'disabled',
ENABLED: 'enabled',
};
@@ -49,7 +53,7 @@ const BOLT_DBUS_CLIENT_IFACE = 'org.freedesktop.bolt1.Manager';
const BOLT_DBUS_NAME = 'org.freedesktop.bolt';
const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
-var Client = class extends Signals.EventEmitter {
+export class Client extends Signals.EventEmitter {
constructor() {
super();
@@ -130,7 +134,7 @@ var Client = class extends Signals.EventEmitter {
};
/* helper class to automatically authorize new devices */
-var AuthRobot = class extends Signals.EventEmitter {
+export class AuthRobot extends Signals.EventEmitter {
constructor(client) {
super();
@@ -222,7 +226,7 @@ var AuthRobot = class extends Signals.EventEmitter {
/* eof client.js */
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js
index d71daadc5..9ca7bd90a 100644
--- a/js/ui/status/volume.js
+++ b/js/ui/status/volume.js
@@ -1,13 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
-const { Clutter, Gio, GLib, GObject, Gvc, St } = imports.gi;
-const Signals = imports.misc.signals;
-
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
-const Slider = imports.ui.slider;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gvc from 'gi://Gvc';
+import St from 'gi://St';
+import * as Signals from '../../misc/signals.js';
+
+import Main from '../main.js';
+import * as PanelMenu from '../panelMenu.js';
+import * as PopupMenu from '../popupMenu.js';
+import * as Slider from '../slider.js';
const ALLOW_AMPLIFIED_VOLUME_KEY = 'allow-volume-above-100-percent';
@@ -19,7 +24,7 @@ const VolumeType = {
// Each Gvc.MixerControl is a connection to PulseAudio,
// so it's better to make it a singleton
let _mixerControl;
-function getMixerControl() {
+export function getMixerControl() {
if (_mixerControl)
return _mixerControl;
@@ -29,7 +34,7 @@ function getMixerControl() {
return _mixerControl;
}
-var StreamSlider = class extends Signals.EventEmitter {
+export class StreamSlider extends Signals.EventEmitter {
constructor(control) {
super();
@@ -217,7 +222,7 @@ var StreamSlider = class extends Signals.EventEmitter {
}
};
-var OutputStreamSlider = class extends StreamSlider {
+export class OutputStreamSlider extends StreamSlider {
constructor(control) {
super(control);
this._slider.accessible_name = _("Volume");
@@ -272,7 +277,7 @@ var OutputStreamSlider = class extends StreamSlider {
}
};
-var InputStreamSlider = class extends StreamSlider {
+export class InputStreamSlider extends StreamSlider {
constructor(control) {
super(control);
this._slider.accessible_name = _("Microphone");
@@ -317,7 +322,7 @@ var InputStreamSlider = class extends StreamSlider {
}
};
-var VolumeMenu = class extends PopupMenu.PopupMenuSection {
+export class VolumeMenu extends PopupMenu.PopupMenuSection {
constructor(control) {
super();
@@ -394,7 +399,7 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
}
};
-var Indicator = GObject.registerClass(
+export const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
diff --git a/js/ui/swipeTracker.js b/js/ui/swipeTracker.js
index 8d96c2dd8..975cae318 100644
--- a/js/ui/swipeTracker.js
+++ b/js/ui/swipeTracker.js
@@ -1,9 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SwipeTracker */
-const { Clutter, Gio, GObject, Meta } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
-const Main = imports.ui.main;
+import Main from './main.js';
// FIXME: ideally these values matches physical touchpad size. We can get the
// correct values for gnome-shell specifically, since mutter uses libinput
@@ -33,6 +36,7 @@ const EPSILON = 0.005;
const GESTURE_FINGER_COUNT = 3;
+/** @enum {number} */
const State = {
NONE: 0,
SCROLLING: 1,
@@ -107,6 +111,12 @@ const TouchpadSwipeGesture = GObject.registerClass({
this._state = TouchpadState.NONE;
this._cumulativeX = 0;
this._cumulativeY = 0;
+
+ /** @type {Clutter.Orientation} */
+ this.orientation;
+ /** @type {boolean} */
+ this.enabled;
+
this._touchpadSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.peripherals.touchpad',
});
@@ -232,6 +242,9 @@ const TouchSwipeGesture = GObject.registerClass({
this.set_n_touch_points(nTouchPoints);
this.set_threshold_trigger_edge(thresholdTriggerEdge);
+ /** @type {Clutter.Orientation} */
+ this.orientation;
+
this._allowedModes = allowedModes;
this._distance = global.screen_height;
@@ -332,6 +345,11 @@ const ScrollGesture = GObject.registerClass({
this._began = false;
this._enabled = true;
+ /** @type {Clutter.Orientation} */
+ this.orientation;
+ /** @type {Clutter.ModifierType} */
+ this.scrollModifiers;
+
actor.connect('scroll-event', this._handleEvent.bind(this));
}
@@ -432,8 +450,14 @@ const ScrollGesture = GObject.registerClass({
// NOTE: duration can be 0 in some cases, in this case it should finish
// instantly.
+/**
+ * @typedef {object} SwipeTrackerParams
+ * @property {boolean} allowDrag
+ * @property {boolean} allowScroll
+ */
+
/** A class for handling swipe gestures */
-var SwipeTracker = GObject.registerClass({
+export const SwipeTracker = GObject.registerClass({
Properties: {
'enabled': GObject.ParamSpec.boolean(
'enabled', 'enabled', 'enabled',
@@ -466,6 +490,9 @@ var SwipeTracker = GObject.registerClass({
super._init();
const { allowDrag = true, allowScroll = true } = params;
+ /** @type {boolean} */
+ this.allowLongSwipes
+
this.orientation = orientation;
this._allowedModes = allowedModes;
this._enabled = true;
@@ -528,7 +555,7 @@ var SwipeTracker = GObject.registerClass({
/**
* canHandleScrollEvent:
* @param {Clutter.Event} scrollEvent: an event to check
- * @returns {bool} whether the event can be handled by the tracker
+ * @returns {boolean} whether the event can be handled by the tracker
*
* This function can be used to combine swipe gesture and mouse
* scrolling.
@@ -631,6 +658,9 @@ var SwipeTracker = GObject.registerClass({
return this._findClosestPoint(pos);
}
+ /**
+ * @returns {[number, number]}
+ */
_getBounds(pos) {
if (this.allowLongSwipes)
return [this._snapPoints[0], this._snapPoints[this._snapPoints.length - 1]];
diff --git a/js/ui/switchMonitor.js b/js/ui/switchMonitor.js
index 5ac582522..50bb2098e 100644
--- a/js/ui/switchMonitor.js
+++ b/js/ui/switchMonitor.js
@@ -1,13 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SwitchMonitorPopup */
-const { Clutter, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const SwitcherPopup = imports.ui.switcherPopup;
-var APP_ICON_SIZE = 96;
+import * as SwitcherPopup from './switcherPopup.js';
-var SwitchMonitorPopup = GObject.registerClass(
+export let APP_ICON_SIZE = 96;
+
+export const SwitchMonitorPopup = GObject.registerClass(
class SwitchMonitorPopup extends SwitcherPopup.SwitcherPopup {
_init() {
let items = [{ icon: 'view-mirror-symbolic',
@@ -69,10 +73,13 @@ class SwitchMonitorPopup extends SwitcherPopup.SwitcherPopup {
}
});
-var SwitchMonitorSwitcher = GObject.registerClass(
+export const SwitchMonitorSwitcher = GObject.registerClass(
class SwitchMonitorSwitcher extends SwitcherPopup.SwitcherList {
+ /**
+ * @param {*} items
+ */
_init(items) {
- super._init(true);
+ super._init({ squareItems: true });
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
diff --git a/js/ui/switcherPopup.js b/js/ui/switcherPopup.js
index b1e273006..209b8507c 100644
--- a/js/ui/switcherPopup.js
+++ b/js/ui/switcherPopup.js
@@ -1,19 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SwitcherPopup, SwitcherList */
-const { Clutter, GLib, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const Main = imports.ui.main;
-var POPUP_DELAY_TIMEOUT = 150; // milliseconds
+import Main from './main.js';
-var POPUP_SCROLL_TIME = 100; // milliseconds
-var POPUP_FADE_OUT_TIME = 100; // milliseconds
+export let POPUP_DELAY_TIMEOUT = 150; // milliseconds
-var DISABLE_HOVER_TIMEOUT = 500; // milliseconds
-var NO_MODS_TIMEOUT = 1500; // milliseconds
+export let POPUP_SCROLL_TIME = 100; // milliseconds
+export let POPUP_FADE_OUT_TIME = 100; // milliseconds
-function mod(a, b) {
+export let DISABLE_HOVER_TIMEOUT = 500; // milliseconds
+export let NO_MODS_TIMEOUT = 1500; // milliseconds
+
+export function mod(a, b) {
return (a + b) % b;
}
@@ -29,10 +34,10 @@ function primaryModifier(mask) {
return primary;
}
-var SwitcherPopup = GObject.registerClass({
+export const SwitcherPopup = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
}, class SwitcherPopup extends St.Widget {
- _init(items) {
+ _init(items, ..._) {
super._init({ style_class: 'switcher-popup',
reactive: true,
visible: false });
@@ -168,6 +173,11 @@ var SwitcherPopup = GObject.registerClass({
return mod(this._selectedIndex - 1, this._items.length);
}
+ /**
+ * @param {*} _keysym
+ * @param {*} _action
+ * @returns {boolean}
+ */
_keyPressHandler(_keysym, _action) {
throw new GObject.NotImplementedError(`_keyPressHandler in ${this.constructor.name}`);
}
@@ -353,7 +363,7 @@ var SwitcherPopup = GObject.registerClass({
}
});
-var SwitcherButton = GObject.registerClass(
+export const SwitcherButton = GObject.registerClass(
class SwitcherButton extends St.Button {
_init(square) {
super._init({ style_class: 'item-box',
@@ -370,7 +380,7 @@ class SwitcherButton extends St.Button {
}
});
-var SwitcherList = GObject.registerClass({
+export const SwitcherList = GObject.registerClass({
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
'item-entered': { param_types: [GObject.TYPE_INT] },
'item-removed': { param_types: [GObject.TYPE_INT] } },
@@ -627,7 +637,7 @@ var SwitcherList = GObject.registerClass({
}
});
-function drawArrow(area, side) {
+export function drawArrow(area, side) {
let themeNode = area.get_theme_node();
let borderColor = themeNode.get_border_color(side);
let bodyColor = themeNode.get_foreground_color();
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index 370385abc..3250878c8 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -1,16 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported UnlockDialog */
-const { AccountsService, Atk, Clutter, Gdm, Gio,
- GnomeDesktop, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const Background = imports.ui.background;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-const SwipeTracker = imports.ui.swipeTracker;
-
-const AuthPrompt = imports.gdm.authPrompt;
+import AccountsService from 'gi://AccountsService';
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import Gdm from 'gi://Gdm';
+import Gio from 'gi://Gio';
+import GnomeDesktop from 'gi://GnomeDesktop';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+
+import * as Background from './background.js';
+import * as Layout from './layout.js';
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
+import * as SwipeTracker from './swipeTracker.js';
+
+import * as AuthPrompt from '../gdm/authPrompt.js';
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
@@ -27,7 +37,7 @@ const BLUR_SIGMA = 60;
const SUMMARY_ICON_SIZE = 32;
-var NotificationsBox = GObject.registerClass({
+export const NotificationsBox = GObject.registerClass({
Signals: { 'wake-up-screen': {} },
}, class NotificationsBox extends St.BoxLayout {
_init() {
@@ -314,7 +324,7 @@ var NotificationsBox = GObject.registerClass({
}
});
-var Clock = GObject.registerClass(
+export const Clock = GObject.registerClass(
class UnlockDialogClock extends St.BoxLayout {
_init() {
super._init({ style_class: 'unlock-dialog-clock', vertical: true });
@@ -387,8 +397,13 @@ class UnlockDialogClock extends St.BoxLayout {
}
});
-var UnlockDialogLayout = GObject.registerClass(
+export const UnlockDialogLayout = GObject.registerClass(
class UnlockDialogLayout extends Clutter.LayoutManager {
+ /**
+ * @param {*} stack
+ * @param {*} notifications
+ * @param {*} switchUserButton
+ */
_init(stack, notifications, switchUserButton) {
super._init();
@@ -466,12 +481,15 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
}
});
-var UnlockDialog = GObject.registerClass({
+export const UnlockDialog = GObject.registerClass({
Signals: {
'failed': {},
'wake-up-screen': {},
},
}, class UnlockDialog extends St.Widget {
+ /**
+ * @param {Clutter.Actor} parentActor
+ */
_init(parentActor) {
super._init({
accessible_role: Atk.Role.WINDOW,
diff --git a/js/ui/userWidget.js b/js/ui/userWidget.js
index bfc91e276..88b0bd8eb 100644
--- a/js/ui/userWidget.js
+++ b/js/ui/userWidget.js
@@ -3,18 +3,32 @@
// A widget showing the user avatar and name
/* exported UserWidget */
-const { Clutter, GLib, GObject, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
-
-var AVATAR_ICON_SIZE = 64;
+export let AVATAR_ICON_SIZE = 64;
// Adapted from gdm/gui/user-switch-applet/applet.c
//
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
// Copyright (C) 2008,2009 Red Hat, Inc.
-var Avatar = GObject.registerClass(
+/**
+ * @typedef {object} AvatarProps: An object with the properties:
+ * @property {string} [styleClass]
+ * @property {boolean} [reactive]
+ * @property {number} [iconSize]
+ */
+
+export const Avatar = GObject.registerClass(
class Avatar extends St.Bin {
+ /**
+ * _init:
+ * @param {import('gi://AccountsService').User} user
+ * @param {Partial<AvatarProps>} [params]
+ */
_init(user, params = {}) {
let themeContext = St.ThemeContext.get_for_stage(global.stage);
const {
@@ -103,8 +117,11 @@ class Avatar extends St.Bin {
}
});
-var UserWidgetLabel = GObject.registerClass(
+export const UserWidgetLabel = GObject.registerClass(
class UserWidgetLabel extends St.Widget {
+ /**
+ * @param {*} user
+ */
_init(user) {
super._init({ layout_manager: new Clutter.BinLayout() });
@@ -186,8 +203,12 @@ class UserWidgetLabel extends St.Widget {
}
});
-var UserWidget = GObject.registerClass(
+export const UserWidget = GObject.registerClass(
class UserWidget extends St.BoxLayout {
+ /**
+ * @param {*} user
+ * @param {*} orientation
+ */
_init(user, orientation = Clutter.Orientation.HORIZONTAL) {
// If user is null, that implies a username-based login authorization.
this._user = user;
diff --git a/js/ui/welcomeDialog.js b/js/ui/welcomeDialog.js
index cf6540fe2..24bc9958b 100644
--- a/js/ui/welcomeDialog.js
+++ b/js/ui/welcomeDialog.js
@@ -1,19 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WelcomeDialog */
-const { Clutter, GObject, Shell, St } = imports.gi;
-
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import * as ModalDialog from './modalDialog.js';
+import Main from './main.js';
const Config = imports.misc.config;
-const Dialog = imports.ui.dialog;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
-
+import * as Dialog from './dialog.js';
var DialogResponse = {
NO_THANKS: 0,
TAKE_TOUR: 1,
};
-var WelcomeDialog = GObject.registerClass(
+export const WelcomeDialog = GObject.registerClass(
class WelcomeDialog extends ModalDialog.ModalDialog {
_init() {
super._init({ styleClass: 'welcome-dialog' });
@@ -26,9 +27,9 @@ class WelcomeDialog extends ModalDialog.ModalDialog {
open() {
if (!this._tourAppInfo)
- return;
+ return false;
- super.open();
+ return super.open();
}
_buildLayout() {
diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js
index 346fad88d..ea856d703 100644
--- a/js/ui/windowAttentionHandler.js
+++ b/js/ui/windowAttentionHandler.js
@@ -1,12 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowAttentionHandler */
-const { GObject, Shell } = imports.gi;
+import GObject from 'gi://GObject';
+import Shell from 'gi://Shell';
-const Main = imports.ui.main;
-const MessageTray = imports.ui.messageTray;
-var WindowAttentionHandler = class {
+import Main from './main.js';
+import * as MessageTray from './messageTray.js';
+
+export class WindowAttentionHandler {
constructor() {
this._tracker = Shell.WindowTracker.get_default();
this._windowDemandsAttentionId = global.display.connect('window-demands-attention',
@@ -34,7 +36,7 @@ var WindowAttentionHandler = class {
return;
let app = this._tracker.get_window_app(window);
- let source = new WindowAttentionSource(app, window);
+ let source = new WindowAttentionSource({ app, window });
Main.messageTray.add(source);
let [title, banner] = this._getTitleAndBanner(app, window);
@@ -54,13 +56,24 @@ var WindowAttentionHandler = class {
}
};
-var WindowAttentionSource = GObject.registerClass(
+/**
+ * @typedef {object} WindowAttentionSourceParams
+ * @property {Shell.App} app
+ * @property {import('gi://Meta').Window} window
+ */
+
+export const WindowAttentionSource = GObject.registerClass(
class WindowAttentionSource extends MessageTray.Source {
- _init(app, window) {
+ /**
+ * @param {import('./messageTray.js').SourceParams & WindowAttentionSourceParams} params
+ */
+ _init(params) {
+ const { window, app } = params;
+
this._window = window;
this._app = app;
- super._init(app.get_name());
+ super._init({ title: app.get_name() });
this.signalIDs = [];
this.signalIDs.push(this._window.connect('notify::demands-attention',
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 2e3e125b6..a1ec2fb40 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -1,39 +1,66 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowManager */
-const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
-
-const AltTab = imports.ui.altTab;
-const AppFavorites = imports.ui.appFavorites;
-const Dialog = imports.ui.dialog;
-const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
-const InhibitShortcutsDialog = imports.ui.inhibitShortcutsDialog;
-const Main = imports.ui.main;
-const ModalDialog = imports.ui.modalDialog;
-const WindowMenu = imports.ui.windowMenu;
-const PadOsd = imports.ui.padOsd;
-const EdgeDragAction = imports.ui.edgeDragAction;
-const CloseDialog = imports.ui.closeDialog;
-const SwitchMonitor = imports.ui.switchMonitor;
-const IBusManager = imports.misc.ibusManager;
-const WorkspaceAnimation = imports.ui.workspaceAnimation;
-
-const { loadInterfaceXML } = imports.misc.fileUtils;
-
-var SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
-var MINIMIZE_WINDOW_ANIMATION_TIME = 200;
-var SHOW_WINDOW_ANIMATION_TIME = 150;
-var DIALOG_SHOW_WINDOW_ANIMATION_TIME = 100;
-var DESTROY_WINDOW_ANIMATION_TIME = 150;
-var DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 100;
-var WINDOW_ANIMATION_TIME = 250;
-var SCROLL_TIMEOUT_TIME = 150;
-var DIM_BRIGHTNESS = -0.3;
-var DIM_TIME = 500;
-var UNDIM_TIME = 250;
-var APP_MOTION_THRESHOLD = 30;
-
-var ONE_SECOND = 1000; // in ms
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
+
+import * as AltTab from './altTab.js';
+import * as AppFavorites from './appFavorites.js';
+import * as Dialog from './dialog.js';
+import * as WorkspaceSwitcherPopup from './workspaceSwitcherPopup.js';
+import * as InhibitShortcutsDialog from './inhibitShortcutsDialog.js';
+import Main from './main.js';
+import * as ModalDialog from './modalDialog.js';
+import * as WindowMenu from './windowMenu.js';
+import * as PadOsd from './padOsd.js';
+import * as EdgeDragAction from './edgeDragAction.js';
+import * as CloseDialog from './closeDialog.js';
+import * as SwipeTracker from './swipeTracker.js';
+import * as SwitchMonitor from './switchMonitor.js';
+import * as IBusManager from '../misc/ibusManager.js';
+import * as WorkspaceAnimation from './workspaceAnimation.js';
+
+import { loadInterfaceXML } from '../misc/fileUtilsModule.js';
+
+export const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
+export const MINIMIZE_WINDOW_ANIMATION_TIME = 200;
+export const SHOW_WINDOW_ANIMATION_TIME = 150;
+export const DIALOG_SHOW_WINDOW_ANIMATION_TIME = 100;
+export const DESTROY_WINDOW_ANIMATION_TIME = 150;
+export const DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 100;
+export const WINDOW_ANIMATION_TIME = 250;
+export const SCROLL_TIMEOUT_TIME = 150;
+export const DIM_BRIGHTNESS = -0.3;
+export const DIM_TIME = 500;
+export const UNDIM_TIME = 250;
+export const APP_MOTION_THRESHOLD = 30;
+
+export const ONE_SECOND = 1000; // in ms
+
+const MOTION_DIRECTIONS = [
+ Meta.MotionDirection.UP,
+ Meta.MotionDirection.DOWN,
+ Meta.MotionDirection.LEFT,
+ Meta.MotionDirection.RIGHT,
+ Meta.MotionDirection.UP_LEFT,
+ Meta.MotionDirection.UP_RIGHT,
+ Meta.MotionDirection.DOWN_LEFT,
+ Meta.MotionDirection.DOWN_RIGHT,
+];
+
+/*
+ * When the last window closed on a workspace is a dialog or splash
+ * screen, we assume that it might be an initial window shown before
+ * the main window of an application, and give the app a grace period
+ * where it can map another window before we remove the workspace.
+ */
+export let LAST_WINDOW_GRACE_TIME = 1000;
var MIN_NUM_WORKSPACES = 2;
@@ -50,8 +77,12 @@ Gio._promisify(Shell,
Gio._promisify(Shell,
'util_stop_systemd_unit', 'util_stop_systemd_unit_finish');
-var DisplayChangeDialog = GObject.registerClass(
+export const DisplayChangeDialog = GObject.registerClass(
class DisplayChangeDialog extends ModalDialog.ModalDialog {
+ /**
+ *
+ * @param {Shell.WM | any} wm
+ */
_init(wm) {
super._init();
@@ -122,7 +153,7 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
});
-var WindowDimmer = GObject.registerClass(
+export const WindowDimmer = GObject.registerClass(
class WindowDimmer extends Clutter.BrightnessContrastEffect {
_init() {
super._init({
@@ -159,7 +190,7 @@ class WindowDimmer extends Clutter.BrightnessContrastEffect {
}
});
-function getWindowDimmer(actor) {
+export function getWindowDimmer(actor) {
let enabled = Meta.prefs_get_attach_modal_dialogs();
let effect = actor.get_effect(WINDOW_DIMMER_EFFECT_NAME);
@@ -172,15 +203,8 @@ function getWindowDimmer(actor) {
return effect;
}
-/*
- * When the last window closed on a workspace is a dialog or splash
- * screen, we assume that it might be an initial window shown before
- * the main window of an application, and give the app a grace period
- * where it can map another window before we remove the workspace.
- */
-var LAST_WINDOW_GRACE_TIME = 1000;
-var WorkspaceTracker = class {
+export class WorkspaceTracker {
constructor(wm) {
this._wm = wm;
@@ -385,7 +409,7 @@ var WorkspaceTracker = class {
}
};
-var TilePreview = GObject.registerClass(
+export const TilePreview = GObject.registerClass(
class TilePreview extends St.Widget {
_init() {
super._init();
@@ -471,7 +495,7 @@ class TilePreview extends St.Widget {
}
});
-var AppSwitchAction = GObject.registerClass({
+export const AppSwitchAction = GObject.registerClass({
Signals: { 'activated': {} },
}, class AppSwitchAction extends Clutter.GestureAction {
_init() {
@@ -532,7 +556,7 @@ var AppSwitchAction = GObject.registerClass({
}
});
-var ResizePopup = GObject.registerClass(
+export const ResizePopup = GObject.registerClass(
class ResizePopup extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
@@ -555,7 +579,7 @@ class ResizePopup extends St.Widget {
}
});
-var WindowManager = class {
+export class WindowManager {
constructor() {
this._shellwm = global.window_manager;
@@ -1398,7 +1422,7 @@ var WindowManager = class {
}
_hasAttachedDialogs(window, ignoreWindow) {
- var count = 0;
+ let count = 0;
window.foreach_transient(win => {
if (win != ignoreWindow &&
win.is_attached_dialog() &&
diff --git a/js/ui/windowMenu.js b/js/ui/windowMenu.js
index 27cecdac2..779d8a7d0 100644
--- a/js/ui/windowMenu.js
+++ b/js/ui/windowMenu.js
@@ -1,13 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*
/* exported WindowMenuManager */
-const { GLib, Meta, St } = imports.gi;
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const BoxPointer = imports.ui.boxpointer;
-const Main = imports.ui.main;
-const PopupMenu = imports.ui.popupMenu;
-var WindowMenu = class extends PopupMenu.PopupMenu {
+import * as BoxPointer from './boxpointer.js';
+import Main from './main.js';
+import * as PopupMenu from './popupMenu.js';
+
+export class WindowMenu extends PopupMenu.PopupMenu {
constructor(window, sourceActor) {
super(sourceActor, 0, St.Side.TOP);
@@ -192,7 +195,7 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
}
};
-var WindowMenuManager = class {
+export class WindowMenuManager {
constructor() {
this._manager = new PopupMenu.PopupMenuManager(Main.layoutManager.dummyCursor);
diff --git a/js/ui/windowPreview.js b/js/ui/windowPreview.js
index e67ec9ec0..d9f82c670 100644
--- a/js/ui/windowPreview.js
+++ b/js/ui/windowPreview.js
@@ -1,28 +1,35 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowPreview */
-const { Atk, Clutter, GLib, GObject,
- Graphene, Meta, Pango, Shell, St } = imports.gi;
+import Atk from 'gi://Atk';
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Graphene from 'gi://Graphene';
+import Meta from 'gi://Meta';
+import Pango from 'gi://Pango';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const DND = imports.ui.dnd;
-const OverviewControls = imports.ui.overviewControls;
+import * as DND from './dnd.js';
+import * as OverviewControls from './overviewControls.js';
-var WINDOW_DND_SIZE = 256;
+export let WINDOW_DND_SIZE = 256;
-var WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
-var WINDOW_OVERLAY_FADE_TIME = 200;
+export let WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
+export let WINDOW_OVERLAY_FADE_TIME = 200;
-var WINDOW_SCALE_TIME = 200;
-var WINDOW_ACTIVE_SIZE_INC = 5; // in each direction
+export let WINDOW_SCALE_TIME = 200;
+export let WINDOW_ACTIVE_SIZE_INC = 5; // in each direction
-var DRAGGING_WINDOW_OPACITY = 100;
+export let DRAGGING_WINDOW_OPACITY = 100;
const ICON_SIZE = 64;
const ICON_OVERLAP = 0.7;
const ICON_TITLE_SPACING = 6;
-var WindowPreview = GObject.registerClass({
+export const WindowPreview = GObject.registerClass({
Properties: {
'overlay-enabled': GObject.ParamSpec.boolean(
'overlay-enabled', 'overlay-enabled', 'overlay-enabled',
@@ -38,6 +45,17 @@ var WindowPreview = GObject.registerClass({
'size-changed': {},
},
}, class WindowPreview extends Shell.WindowPreview {
+ /** @returns {Clutter.Actor<Shell.WindowPreviewLayout>} */
+ get window_container() {
+ // Cast the window_container to the appropriate type...
+
+ return /** @type {Clutter.Actor<Shell.WindowPreviewLayout>} */ (super.window_container);
+ }
+
+ set window_container(window_container) {
+ super.window_container = window_container;
+ }
+
_init(metaWindow, workspace, overviewAdjustment) {
this.metaWindow = metaWindow;
this.metaWindow._delegate = this;
@@ -54,6 +72,7 @@ var WindowPreview = GObject.registerClass({
const windowContainer = new Clutter.Actor({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ layout_manager: /** @type {Shell.WindowPreviewLayout} */ (null),
});
this.window_container = windowContainer;
@@ -628,6 +647,8 @@ var WindowPreview = GObject.registerClass({
let [x, y] = action.get_coords();
action.release();
this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device());
+
+ return false;
});
} else {
this.showOverlay(true);
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 1c3a15710..71cbf1a9c 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -1,26 +1,31 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Workspace */
-const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import St from 'gi://St';
+import Graphene from 'gi://Graphene';
-const Background = imports.ui.background;
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const OverviewControls = imports.ui.overviewControls;
-const Util = imports.misc.util;
-const { WindowPreview } = imports.ui.windowPreview;
+import * as Background from './background.js';
+import * as DND from './dnd.js';
+import Main from './main.js';
+import Meta from 'gi://Meta';
+import * as OverviewControls from './overviewControls.js';
+import * as Util from '../misc/util.js';
+import { WindowPreview } from './windowPreview.js';
-var WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
+export let WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
-var WINDOW_REPOSITIONING_DELAY = 750;
+export let WINDOW_REPOSITIONING_DELAY = 750;
// When calculating a layout, we calculate the scale of windows and the percent
// of the available area the new layout uses. If the values for the new layout,
// when weighted with the values as below, are worse than the previous layout's,
// we stop looking for a new layout and use the previous layout.
// Otherwise, we keep looking for a new layout.
-var LAYOUT_SCALE_WEIGHT = 1;
-var LAYOUT_SPACE_WEIGHT = 0.1;
+export let LAYOUT_SCALE_WEIGHT = 1;
+export let LAYOUT_SPACE_WEIGHT = 0.1;
const BACKGROUND_CORNER_RADIUS_PIXELS = 30;
const BACKGROUND_MARGIN = 12;
@@ -95,7 +100,7 @@ const BACKGROUND_MARGIN = 12;
// each window's "cell" area to be the same, but we shrink the thumbnail
// and center it horizontally, and align it to the bottom vertically.
-var LayoutStrategy = class {
+export class LayoutStrategy {
constructor(params = {}) {
const {
monitor = null,
@@ -388,7 +393,7 @@ function animateAllocation(actor, box) {
return actor.get_transition('allocation');
}
-var WorkspaceLayout = GObject.registerClass({
+export const WorkspaceLayout = GObject.registerClass({
Properties: {
'spacing': GObject.ParamSpec.double(
'spacing', 'Spacing', 'Spacing',
@@ -572,8 +577,9 @@ var WorkspaceLayout = GObject.registerClass({
_syncWorkareaTracking() {
if (this._container) {
- if (this._workAreaChangedId)
- return;
+ // FIXME
+ // if (this._workAreaChangedId)
+ // return;
this._workarea = Main.layoutManager.getWorkAreaForMonitor(this._monitorIndex);
this._workareasChangedId =
global.display.connect('workareas-changed', () => {
@@ -592,6 +598,9 @@ var WorkspaceLayout = GObject.registerClass({
this._stateAdjustment.actor = container;
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width(container, forHeight) {
const workarea = this._getAdjustedWorkarea(container);
if (forHeight === -1)
@@ -603,6 +612,9 @@ var WorkspaceLayout = GObject.registerClass({
return [0, widthPreservingAspectRatio];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height(container, forWidth) {
const workarea = this._getAdjustedWorkarea(container);
if (forWidth === -1)
@@ -765,7 +777,7 @@ var WorkspaceLayout = GObject.registerClass({
/**
* addWindow:
- * @param {WindowPreview} window: the window to add
+ * @param {WindowPreview["prototype"]} window: the window to add
* @param {Meta.Window} metaWindow: the MetaWindow of the window
*
* Adds @window to the workspace, it will be shown immediately if
@@ -806,7 +818,7 @@ var WorkspaceLayout = GObject.registerClass({
/**
* removeWindow:
- * @param {WindowPreview} window: the window to remove
+ * @param {WindowPreview["prototype"]} window: the window to remove
*
* Removes @window from the workspace if @window is a part of the
* workspace. If the layout-frozen property is set to true, the
@@ -1055,7 +1067,8 @@ class WorkspaceBackground extends St.Widget {
/**
* @metaWorkspace: a #Meta.Workspace, or null
*/
-var Workspace = GObject.registerClass(
+export const Workspace = GObject.registerClass(
+/** @extends {St.Widget<typeof WorkspaceLayout["prototype"]>} */
class Workspace extends St.Widget {
_init(metaWorkspace, monitorIndex, overviewAdjustment) {
super._init({
@@ -1077,6 +1090,7 @@ class Workspace extends St.Widget {
reactive: true,
x_expand: true,
y_expand: true,
+ layout_manager: /** @type {WorkspaceLayout["prototype"]} */ (null),
});
this._container.layout_manager = layoutManager;
this.add_child(this._container);
@@ -1216,6 +1230,9 @@ class Workspace extends St.Widget {
'[gnome-shell] this._layoutFrozenId');
}
+ /**
+ * @param {Meta.Window} metaWin
+ */
_doAddWindow(metaWin) {
let win = metaWin.get_compositor_private();
diff --git a/js/ui/workspaceAnimation.js b/js/ui/workspaceAnimation.js
index d240fe156..5bd8db359 100644
--- a/js/ui/workspaceAnimation.js
+++ b/js/ui/workspaceAnimation.js
@@ -1,12 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspaceAnimationController */
-const { Clutter, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Background = imports.ui.background;
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
-const SwipeTracker = imports.ui.swipeTracker;
+import * as Background from './background.js';
+import * as Layout from './layout.js';
+import * as SwipeTracker from './swipeTracker.js';
+
+import Main from './main.js';
const WINDOW_ANIMATION_TIME = 250;
const WORKSPACE_SPACING = 100;
@@ -267,7 +272,7 @@ const MonitorGroup = GObject.registerClass({
}
});
-var WorkspaceAnimationController = class {
+export class WorkspaceAnimationController {
constructor() {
this._movingWindow = null;
this._switchData = null;
diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js
index 5b65bec8a..a85fb4a35 100644
--- a/js/ui/workspaceSwitcherPopup.js
+++ b/js/ui/workspaceSwitcherPopup.js
@@ -1,14 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspaceSwitcherPopup */
-const { Clutter, GLib, GObject, Meta, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
-const Main = imports.ui.main;
-var ANIMATION_TIME = 100;
-var DISPLAY_TIMEOUT = 600;
+import Main from './main.js';
-var WorkspaceSwitcherPopupList = GObject.registerClass(
+ export let ANIMATION_TIME = 100;
+ export let DISPLAY_TIMEOUT = 600;
+
+export const WorkspaceSwitcherPopupList = GObject.registerClass(
class WorkspaceSwitcherPopupList extends St.Widget {
_init() {
super._init({
@@ -63,6 +68,9 @@ class WorkspaceSwitcherPopupList extends St.Widget {
}
}
+ /**
+ * @return {[number, number]}
+ */
_getSizeForOppositeOrientation() {
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
@@ -119,7 +127,7 @@ class WorkspaceSwitcherPopupList extends St.Widget {
}
});
-var WorkspaceSwitcherPopup = GObject.registerClass(
+export const WorkspaceSwitcherPopup = GObject.registerClass(
class WorkspaceSwitcherPopup extends St.Widget {
_init() {
super._init({ x: 0,
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 412527c93..c18cb5b67 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -1,50 +1,69 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspaceThumbnail, ThumbnailsBox */
-const { Clutter, Gio, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+import Graphene from 'gi://Graphene';
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const Util = imports.misc.util;
-const Workspace = imports.ui.workspace;
+
+
+import * as DND from './dnd.js';
+import Main from './main.js';
+import * as WindowPreview from './windowPreview.js';
+import * as Util from '../misc/util.js'
const NUM_WORKSPACES_THRESHOLD = 2;
// The maximum size of a thumbnail is 5% the width and height of the screen
-var MAX_THUMBNAIL_SCALE = 0.05;
+export const MAX_THUMBNAIL_SCALE = 0.05;
-var RESCALE_ANIMATION_TIME = 200;
-var SLIDE_ANIMATION_TIME = 200;
+
+export let RESCALE_ANIMATION_TIME = 200;
+export let SLIDE_ANIMATION_TIME = 200;
// When we create workspaces by dragging, we add a "cut" into the top and
// bottom of each workspace so that the user doesn't have to hit the
// placeholder exactly.
-var WORKSPACE_CUT_SIZE = 10;
+export let WORKSPACE_CUT_SIZE = 10;
-var WORKSPACE_KEEP_ALIVE_TIME = 100;
+export let WORKSPACE_KEEP_ALIVE_TIME = 100;
-var MUTTER_SCHEMA = 'org.gnome.mutter';
+const MUTTER_SCHEMA = 'org.gnome.mutter';
/* A layout manager that requests size only for primary_actor, but then allocates
all using a fixed layout */
-var PrimaryActorLayout = GObject.registerClass(
+export const PrimaryActorLayout = GObject.registerClass(
class PrimaryActorLayout extends Clutter.FixedLayout {
+ /**
+ * @param {Clutter.Actor} primaryActor
+ */
_init(primaryActor) {
super._init();
this.primaryActor = primaryActor;
}
- vfunc_get_preferred_width(container, forHeight) {
+ /**
+ * @param {number} forHeight
+ */
+ vfunc_get_preferred_width(_, forHeight) {
return this.primaryActor.get_preferred_width(forHeight);
}
- vfunc_get_preferred_height(container, forWidth) {
+ /**
+ * @param {number} forWidth
+ */
+ vfunc_get_preferred_height(_, forWidth) {
return this.primaryActor.get_preferred_height(forWidth);
}
});
-var WindowClone = GObject.registerClass({
+export const WindowClone = GObject.registerClass({
Signals: {
'drag-begin': {},
'drag-cancelled': {},
@@ -52,6 +71,9 @@ var WindowClone = GObject.registerClass({
'selected': { param_types: [GObject.TYPE_UINT] },
},
}, class WindowClone extends Clutter.Actor {
+ /**
+ * @param {Meta.WindowActor} realWindow
+ */
_init(realWindow) {
let clone = new Clutter.Clone({ source: realWindow });
super._init({
@@ -78,14 +100,15 @@ var WindowClone = GObject.registerClass({
this._draggable = DND.makeDraggable(this,
{ restoreOnSuccess: true,
- dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
- dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
+ dragActorMaxSize: WindowPreview.WINDOW_DND_SIZE,
+ dragActorOpacity: WindowPreview.DRAGGING_WINDOW_OPACITY });
this._draggable.connect('drag-begin', this._onDragBegin.bind(this));
this._draggable.connect('drag-cancelled', this._onDragCancelled.bind(this));
this._draggable.connect('drag-end', this._onDragEnd.bind(this));
this.inDrag = false;
let iter = win => {
+ /** @type {Meta.Window} */
let actor = win.get_compositor_private();
if (!actor)
@@ -163,7 +186,8 @@ var WindowClone = GObject.registerClass({
}
_disconnectSignals() {
- this.get_children().forEach(child => {
+ /** @type {Clutter.Clone[]} */
+ (this.get_children()).forEach(child => {
let realWindow = child.source;
realWindow.disconnect(child._updateId);
@@ -230,7 +254,7 @@ var WindowClone = GObject.registerClass({
});
-var ThumbnailState = {
+export const ThumbnailState = {
NEW: 0,
EXPANDING: 1,
EXPANDED: 2,
@@ -246,7 +270,7 @@ var ThumbnailState = {
/**
* @metaWorkspace: a #Meta.Workspace
*/
-var WorkspaceThumbnail = GObject.registerClass({
+export const WorkspaceThumbnail = GObject.registerClass({
Properties: {
'collapse-fraction': GObject.ParamSpec.double(
'collapse-fraction', 'collapse-fraction', 'collapse-fraction',
@@ -607,7 +631,7 @@ var WorkspaceThumbnail = GObject.registerClass({
});
-var ThumbnailsBox = GObject.registerClass({
+export const ThumbnailsBox = GObject.registerClass({
Properties: {
'expand-fraction': GObject.ParamSpec.double(
'expand-fraction', 'expand-fraction', 'expand-fraction',
@@ -1258,6 +1282,8 @@ var ThumbnailsBox = GObject.registerClass({
},
});
});
+
+ return false;
}
_queueUpdateStates() {
@@ -1408,6 +1434,8 @@ var ThumbnailsBox = GObject.registerClass({
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.hide();
+
+ return false;
});
}
@@ -1438,6 +1466,8 @@ var ThumbnailsBox = GObject.registerClass({
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.show();
+
+ return false;
});
x += placeholderWidth + spacing;
}
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 6dad2df3f..c2355905d 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -1,19 +1,29 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspacesView, WorkspacesDisplay */
-const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
-const Layout = imports.ui.layout;
-const Main = imports.ui.main;
-const OverviewControls = imports.ui.overviewControls;
-const SwipeTracker = imports.ui.swipeTracker;
-const Util = imports.misc.util;
-const Workspace = imports.ui.workspace;
-const { ThumbnailsBox, MAX_THUMBNAIL_SCALE } = imports.ui.workspaceThumbnail;
-var WORKSPACE_SWITCH_TIME = 250;
+import { ThumbnailsBox, MAX_THUMBNAIL_SCALE } from './workspaceThumbnail.js';
-const MUTTER_SCHEMA = 'org.gnome.mutter';
+import * as Util from '../misc/util.js';
+import * as SwipeTracker from './swipeTracker.js';
+import * as Workspace from './workspace.js';
+import * as OverviewControls from './overviewControls.js';
+import * as Layout from './layout.js';
+
+import Main from './main.js'
+
+import { ANIMATION_TIME } from '../ui/overview.js';
+
+export var WORKSPACE_SWITCH_TIME = 250;
+
+export const MUTTER_SCHEMA = 'org.gnome.mutter';
const WORKSPACE_MIN_SPACING = 24;
const WORKSPACE_MAX_SPACING = 80;
@@ -81,21 +91,27 @@ var WorkspacesViewBase = GObject.registerClass({
child.allocate_available_size(0, 0, box.get_width(), box.get_height());
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_width() {
return [0, 0];
}
+ /**
+ * @returns {[number, number]}
+ */
vfunc_get_preferred_height() {
return [0, 0];
}
});
-var FitMode = {
+export const FitMode = {
SINGLE: 0,
ALL: 1,
};
-var WorkspacesView = GObject.registerClass(
+export const WorkspacesView = GObject.registerClass(
class WorkspacesView extends WorkspacesViewBase {
_init(monitorIndex, controls, scrollAdjustment, fitModeAdjustment, overviewAdjustment) {
let workspaceManager = global.workspace_manager;
@@ -291,6 +307,9 @@ class WorkspacesView extends WorkspacesViewBase {
}
}
+ /**
+ * @param {Clutter.ActorBox} box
+ */
_getInitialBoxes(box) {
const offsetBox = new Clutter.ActorBox();
offsetBox.set_size(...box.get_size());
@@ -546,7 +565,7 @@ class WorkspacesView extends WorkspacesViewBase {
}
});
-var ExtraWorkspaceView = GObject.registerClass(
+export const ExtraWorkspaceView = GObject.registerClass(
class ExtraWorkspaceView extends WorkspacesViewBase {
_init(monitorIndex, overviewAdjustment) {
super._init(monitorIndex, overviewAdjustment);
@@ -828,7 +847,7 @@ class SecondaryMonitorDisplay extends St.Widget {
}
});
-var WorkspacesDisplay = GObject.registerClass(
+export const WorkspacesDisplay = GObject.registerClass(
class WorkspacesDisplay extends St.Widget {
_init(controls, scrollAdjustment, overviewAdjustment) {
super._init({
diff --git a/js/ui/xdndHandler.js b/js/ui/xdndHandler.js
index 4154b7f39..d45c9bfcf 100644
--- a/js/ui/xdndHandler.js
+++ b/js/ui/xdndHandler.js
@@ -1,13 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported XdndHandler */
-const { Clutter } = imports.gi;
-const Signals = imports.misc.signals;
+import Clutter from 'gi://Clutter';
+import Main from './main.js';
+import * as Signals from '../misc/signals.js';
+import * as DND from './dnd.js';
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-
-var XdndHandler = class extends Signals.EventEmitter {
+export class XdndHandler extends Signals.EventEmitter {
constructor() {
super();
@@ -104,7 +103,7 @@ var XdndHandler = class extends Signals.EventEmitter {
}
while (pickedActor) {
- if (pickedActor._delegate && pickedActor._delegate.handleDragOver) {
+ if (pickedActor._delegate && DND.handlesDragOver(pickedActor._delegate)) {
let [r_, targX, targY] = pickedActor.transform_stage_point(x, y);
let result = pickedActor._delegate.handleDragOver(this,
dragEvent.dragActor,
diff --git a/src/main.c b/src/main.c
index 3cd9e10a5..9a4246152 100644
--- a/src/main.c
+++ b/src/main.c
@@ -393,8 +393,8 @@ list_modes (const char *option_name,
shell_introspection_init ();
- script = "imports.ui.environment.init();"
- "imports.ui.sessionMode.listModes();";
+ script = ""
+ "";
if (!gjs_context_eval (context, script, -1, "<main>", &status, NULL))
g_message ("Retrieving list of available modes failed.");
diff --git a/tests/interactive/background-repeat.js b/tests/interactive/background-repeat.js
index 1377f7424..3179a8a08 100644
--- a/tests/interactive/background-repeat.js
+++ b/tests/interactive/background-repeat.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage({ width: 640, height: 480 });
diff --git a/tests/interactive/background-size.js b/tests/interactive/background-size.js
index 8f8738da9..367f47e11 100644
--- a/tests/interactive/background-size.js
+++ b/tests/interactive/background-size.js
@@ -2,7 +2,11 @@
const UI = imports.testcommon.ui;
-const { Cogl, Clutter, Meta, St } = imports.gi;
+import Cogl from 'gi://Cogl';
+import Clutter from 'gi://Clutter';
+import Meta from 'gi://Meta';
+import St from 'gi://St';
+
function test() {
diff --git a/tests/interactive/border-radius.js b/tests/interactive/border-radius.js
index 4d26518bd..a5eb6a3a7 100644
--- a/tests/interactive/border-radius.js
+++ b/tests/interactive/border-radius.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage({ width: 640, height: 480 });
diff --git a/tests/interactive/border-width.js b/tests/interactive/border-width.js
index 30c7575a0..4d71d443f 100644
--- a/tests/interactive/border-width.js
+++ b/tests/interactive/border-width.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage({ width: 640, height: 480 });
diff --git a/tests/interactive/borders.js b/tests/interactive/borders.js
index 4812acbfa..aa76720bb 100644
--- a/tests/interactive/borders.js
+++ b/tests/interactive/borders.js
@@ -2,7 +2,8 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
function test() {
let stage = new Clutter.Stage({ width: 640, height: 480 });
diff --git a/tests/interactive/box-layout.js b/tests/interactive/box-layout.js
index bb9a5bbc2..ec1550b70 100644
--- a/tests/interactive/box-layout.js
+++ b/tests/interactive/box-layout.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/interactive/box-shadow-animated.js b/tests/interactive/box-shadow-animated.js
index cf117a7f3..4d5753029 100644
--- a/tests/interactive/box-shadow-animated.js
+++ b/tests/interactive/box-shadow-animated.js
@@ -2,7 +2,10 @@
const UI = imports.testcommon.ui;
-const { Clutter, GLib, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import St from 'gi://St';
+
const DELAY = 2000;
@@ -22,7 +25,7 @@ function resize_animated(label) {
}
}
-function get_css_style(shadow_style)
+export function get_css_style(shadow_style)
{
return 'border: 20px solid black;' +
'border-radius: 20px;' +
diff --git a/tests/interactive/box-shadows.js b/tests/interactive/box-shadows.js
index c9c677c97..077cf18dd 100644
--- a/tests/interactive/box-shadows.js
+++ b/tests/interactive/box-shadows.js
@@ -2,7 +2,8 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
function test() {
let stage = new Clutter.Stage({ width: 640, height: 480 });
diff --git a/tests/interactive/calendar.js b/tests/interactive/calendar.js
index d1d435a52..6098ecbb7 100644
--- a/tests/interactive/calendar.js
+++ b/tests/interactive/calendar.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage({ width: 400, height: 400 });
diff --git a/tests/interactive/css-fonts.js b/tests/interactive/css-fonts.js
index a25769318..c6d581ac1 100644
--- a/tests/interactive/css-fonts.js
+++ b/tests/interactive/css-fonts.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/interactive/entry.js b/tests/interactive/entry.js
index 9ae010604..0860aa7ce 100644
--- a/tests/interactive/entry.js
+++ b/tests/interactive/entry.js
@@ -2,7 +2,10 @@
const UI = imports.testcommon.ui;
-const { Clutter, GLib, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GLib from 'gi://GLib';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage({ width: 400, height: 400 });
diff --git a/tests/interactive/gapplication.js b/tests/interactive/gapplication.js
index ec38b806f..565b72608 100755
--- a/tests/interactive/gapplication.js
+++ b/tests/interactive/gapplication.js
@@ -1,8 +1,14 @@
#!/usr/bin/env gjs
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-imports.gi.versions = { Gdk: '3.0', Gtk: '3.0' };
-const { Gdk, Gio, GLib, Gtk } = imports.gi;
+import 'gi://Gtk?version=3.0';
+import 'gi://Gdk?version=3.0';
+
+import Gdk from 'gi://Gdk';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import Gtk from 'gi://Gtk';
+
function do_action(action, parameter) {
print ("Action '" + action.name + "' invoked");
diff --git a/tests/interactive/icons.js b/tests/interactive/icons.js
index 65b7f6560..54441d52b 100644
--- a/tests/interactive/icons.js
+++ b/tests/interactive/icons.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/interactive/inline-style.js b/tests/interactive/inline-style.js
index 3952c3a98..1439ca44c 100644
--- a/tests/interactive/inline-style.js
+++ b/tests/interactive/inline-style.js
@@ -2,7 +2,9 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/interactive/scroll-view-sizing.js b/tests/interactive/scroll-view-sizing.js
index a6c682e54..0b07414f3 100644
--- a/tests/interactive/scroll-view-sizing.js
+++ b/tests/interactive/scroll-view-sizing.js
@@ -2,7 +2,12 @@
const UI = imports.testcommon.ui;
-const { Clutter, GObject, Gtk, Shell, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import Shell from 'gi://Shell';
+import St from 'gi://St';
+
// This is an interactive test of the sizing behavior of StScrollView. It
// may be interesting in the future to split out the two classes at the
@@ -28,7 +33,7 @@ const BOX_WIDTHS = [
const SPACING = 10;
-var FlowedBoxes = GObject.registerClass(
+export const FlowedBoxes = GObject.registerClass(
class FlowedBoxes extends St.Widget {
_init() {
super._init();
@@ -117,7 +122,7 @@ class FlowedBoxes extends St.Widget {
//
// This is currently only written for the case where the child is height-for-width
-var SizingIllustrator = GObject.registerClass(
+export const SizingIllustrator = GObject.registerClass(
class SizingIllustrator extends St.Widget {
_init() {
super._init();
diff --git a/tests/interactive/scrolling.js b/tests/interactive/scrolling.js
index 91951ce10..50d1aaa5a 100644
--- a/tests/interactive/scrolling.js
+++ b/tests/interactive/scrolling.js
@@ -2,7 +2,10 @@
const UI = imports.testcommon.ui;
-const { Clutter, Gtk, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import Gtk from 'gi://Gtk';
+import St from 'gi://St';
+
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/interactive/test-title.js b/tests/interactive/test-title.js
index 0a468ddd5..09e2c62ac 100755
--- a/tests/interactive/test-title.js
+++ b/tests/interactive/test-title.js
@@ -1,8 +1,9 @@
#!/usr/bin/env gjs
-imports.gi.versions.Gtk = '3.0';
+import 'gi://Gtk?version=3.0';
-const { GLib, Gtk } = imports.gi;
+import GLib from 'gi://GLib';
+import Gtk from 'gi://Gtk';
function nextTitle() {
let length = Math.random() * 20;
diff --git a/tests/interactive/transitions.js b/tests/interactive/transitions.js
index 7b2eac1c7..a9e39ecfc 100644
--- a/tests/interactive/transitions.js
+++ b/tests/interactive/transitions.js
@@ -2,7 +2,8 @@
const UI = imports.testcommon.ui;
-const { Clutter, St } = imports.gi;
+import Clutter from 'gi://Clutter';
+import St from 'gi://St';
function test() {
let stage = new Clutter.Stage();
diff --git a/tests/testcommon/ui.js b/tests/testcommon/ui.js
index abacea5f7..b98fb4567 100644
--- a/tests/testcommon/ui.js
+++ b/tests/testcommon/ui.js
@@ -1,12 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const Config = imports.misc.config;
+import 'gi://Clutter?version=9';
+import 'gi://Gtk?version=3.0';
-imports.gi.versions = { Clutter: Config.LIBMUTTER_API_VERSION, Gtk: '3.0' };
+import Clutter from 'gi://Clutter';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import St from 'gi://St';
-const { Clutter, Gio, GLib, St } = imports.gi;
-
-const Environment = imports.ui.environment;
+import * as Environment from '../../js/ui/environment.js';
function init(stage) {
Environment.init();
diff --git a/tests/unit/markup.js b/tests/unit/markup.js
index 603ca8194..352717929 100644
--- a/tests/unit/markup.js
+++ b/tests/unit/markup.js
@@ -3,12 +3,11 @@
// Test cases for MessageList markup parsing
const JsUnit = imports.jsUnit;
-const Pango = imports.gi.Pango;
+import Pango from 'gi://Pango';
const Environment = imports.ui.environment;
Environment.init();
-const Main = imports.ui.main; // unused, but needed to break dependency loop
const MessageList = imports.ui.messageList;
// Assert that @input, assumed to be markup, gets "fixed" to @output,