ESM Part 1

This commit is contained in:
Evan Welsh 2021-09-17 23:48:04 -07:00
parent ff88b5ab91
commit 91d6953ee6
No known key found for this signature in database
GPG key ID: 091203D0E8238805
163 changed files with 4763 additions and 2846 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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();

View file

@ -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();

View file

@ -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;
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';
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 * 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 });

View file

@ -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();

View file

@ -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();

View file

@ -3,15 +3,18 @@
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor,
ShellUserVerifier */
const { Clutter, Gdm, Gio, GLib } = imports.gi;
const Signals = imports.misc.signals;
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';
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 * 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();

View file

@ -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();

View file

@ -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>

19
js/misc/config.d.ts vendored Normal file
View file

@ -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;

View file

@ -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@';

View file

@ -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)
@ -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,21 +254,24 @@ 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':
@ -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()

117
js/misc/fileUtilsModule.js Normal file
View file

@ -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);
}

View file

@ -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,

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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 {

View file

@ -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;

View file

@ -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

View file

@ -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()

View file

@ -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',

View file

@ -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]);

6
js/misc/params.d.ts vendored Normal file
View file

@ -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;

View file

@ -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))

View file

@ -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. Its possible for the users parental controls
// to change at runtime if the Parental Controls application is used by an
// administrator from within the users session.
var ParentalControlsManager = GObject.registerClass({
export const ParentalControlsManager = GObject.registerClass({
Signals: {
'app-filter-changed': {},
},

View file

@ -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',

9
js/misc/signals.d.ts vendored Normal file
View file

@ -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);
}

View file

@ -1,5 +1,6 @@
/** @type {import("environment").SignalsNamespace} */
const Signals = imports.signals;
var EventEmitter = class EventEmitter {};
export class EventEmitter {}
Signals.addSignalMethods(EventEmitter.prototype);

View file

@ -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();

View file

@ -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();

View file

@ -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
*/

View file

@ -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';
// Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
export let UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
var WeatherClient = class extends Signals.EventEmitter {
// Minimum time between updates to show loading indication
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;

View file

@ -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 */

View file

@ -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" },

View file

@ -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" },

View file

@ -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;

View file

@ -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);

View file

@ -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;
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';
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
export let ANIMATED_ICON_UPDATE_TIMEOUT = 16;
export let SPINNER_ANIMATION_TIME = 300;
export let SPINNER_ANIMATION_DELAY = 1000;
var Animation = GObject.registerClass(
/**
* @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,

View file

@ -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;
import Clutter from 'gi://Clutter';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gio from 'gi://Gio';
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;
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';
var MENU_POPUP_TIMEOUT = 600;
var POPDOWN_DIALOG_TIMEOUT = 500;
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';
var FOLDER_SUBICON_FRACTION = .4;
export const MENU_POPUP_TIMEOUT = 600;
export const POPDOWN_DIALOG_TIMEOUT = 500;
var VIEWS_SWITCH_TIME = 400;
var VIEWS_SWITCH_ANIMATION_DELAY = 100;
export const FOLDER_SUBICON_FRACTION = .4;
var SCROLL_TIMEOUT_TIME = 150;
export const VIEWS_SWITCH_TIME = 400;
export const VIEWS_SWITCH_ANIMATION_DELAY = 100;
var APP_ICON_SCALE_IN_TIME = 500;
var APP_ICON_SCALE_IN_DELAY = 700;
export const SCROLL_TIMEOUT_TIME = 150;
var APP_ICON_TITLE_EXPAND_TIME = 200;
var APP_ICON_TITLE_COLLAPSE_TIME = 100;
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);

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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',

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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({

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
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';
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 * 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;

View file

@ -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;
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';
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 * 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;

View file

@ -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;
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';
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 * 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;

View file

@ -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,8 +82,27 @@ const ChatMessage = HAVE_TP ? GObject.registerClass({
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
},
}, class ChatMessageClass extends GObject.Object {
static newFromTpMessage(tpMessage, 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],
@ -81,9 +111,9 @@ const ChatMessage = HAVE_TP ? GObject.registerClass({
? tpMessage.get_received_timestamp() : tpMessage.get_sent_timestamp(),
direction,
});
}
}
static newFromTplTextEvent(tplTextEvent) {
function newChatMessageFromTplTextEvent(tplTextEvent) {
let direction =
tplTextEvent.get_sender().get_entity_type() === Tpl.EntityType.SELF
? NotificationDirection.SENT : NotificationDirection.RECEIVED;
@ -95,11 +125,9 @@ const ChatMessage = HAVE_TP ? GObject.registerClass({
'timestamp': tplTextEvent.get_timestamp(),
direction,
});
}
}) : null;
}
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;

View file

@ -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);

View file

@ -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;
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';
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;
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';
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;
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;
function getAppFromSource(source) {
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)

View file

@ -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;
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';
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;
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';
const { loadInterfaceXML } = imports.misc.fileUtils;
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;

View file

@ -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();

View file

@ -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;
var DragMotionResult = {
/** @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);
}
/**
* @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);
}

View file

@ -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;

View file

@ -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;
import Clutter from 'gi://Clutter';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gio from 'gi://Gio';
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;
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';
const { loadInterfaceXML } = imports.misc.fileUtils;
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);
});

View file

@ -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;
const Soup_ = gi.require('Soup', '3.0');
} catch (e) {
imports.gi.versions.Soup = '2.4';
const { Soup } = imports.gi;
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,7 +49,6 @@ 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
@ -50,8 +56,7 @@ 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];
for (let prop in props) meta[prop] = props[prop];
};
// clutter_container_add() actually is a an add-many-actors
@ -59,20 +64,18 @@ function _patchContainerClass(containerClass) {
// 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);
if (props) this.child_set(actor, props);
};
}
function _patchLayoutClass(layoutClass, styleProps) {
if (styleProps) {
layoutClass.prototype.hookup_style = function (container) {
container.connect('style-changed', () => {
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 (found) this[prop] = length;
}
});
};
@ -122,31 +125,28 @@ function _makeEaseCallback(params, cleanup) {
let onStopped = params.onStopped;
delete params.onStopped;
return isFinished => {
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];
if (!propName.startsWith("@")) return [actor, propName];
let [type, name, prop] = propName.split('.');
let [type, name, prop] = propName.split(".");
switch (type) {
case '@layout':
case "@layout":
return [actor.layout_manager, name];
case '@actions':
case "@actions":
return [actor.get_action(name), prop];
case '@constraints':
case "@constraints":
return [actor.get_constraint(name), prop];
case '@content':
case "@content":
return [actor.content, name];
case '@effects':
case "@effects":
return [actor.get_effect(name), prop];
}
@ -156,22 +156,18 @@ function _getPropertyTarget(actor, propName) {
function _easeActor(actor, params) {
actor.save_easing_state();
if (params.duration != undefined)
actor.set_easing_duration(params.duration);
if (params.duration != undefined) actor.set_easing_duration(params.duration);
delete params.duration;
if (params.delay != undefined)
actor.set_easing_delay(params.delay);
if (params.delay != undefined) actor.set_easing_delay(params.delay);
delete params.delay;
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
if (params.repeatCount != undefined) repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
if (params.autoReverse != undefined) autoReverse = params.autoReverse;
delete params.autoReverse;
// repeatCount doesn't include the initial iteration
@ -179,8 +175,7 @@ function _easeActor(actor, params) {
// whether the transition should finish where it started
const isReversed = autoReverse && numIterations % 2 === 0;
if (params.mode != undefined)
actor.set_easing_mode(params.mode);
if (params.mode != undefined) actor.set_easing_mode(params.mode);
delete params.mode;
const prepare = () => {
@ -194,24 +189,20 @@ function _easeActor(actor, params) {
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));
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);
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);
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.delay) transition.connect("started", () => prepare());
else prepare();
if (transition) {
transition.set({ repeatCount, autoReverse });
transition.connect('stopped', (t, finished) => callback(finished));
transition.connect("stopped", (t, finished) => callback(finished));
} else {
callback(true);
}
@ -219,22 +210,18 @@ function _easeActor(actor, params) {
function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease()
if (params.mode)
params.progress_mode = params.mode;
if (params.mode) params.progress_mode = params.mode;
delete params.mode;
if (params.duration)
params.duration = adjustAnimationTime(params.duration);
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;
if (params.repeatCount != undefined) repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
if (params.autoReverse != undefined) autoReverse = params.autoReverse;
delete params.autoReverse;
// repeatCount doesn't include the initial iteration
@ -244,8 +231,7 @@ function _easeActorProperty(actor, propName, target, params) {
// Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
if (actor instanceof Clutter.Actor && !actor.mapped) duration = 0;
const prepare = () => {
Meta.disable_unredirect_for_display(global.display);
@ -263,8 +249,7 @@ function _easeActorProperty(actor, propName, target, params) {
if (duration == 0) {
let [obj, prop] = _getPropertyTarget(actor, propName);
if (!isReversed)
obj[prop] = target;
if (!isReversed) obj[prop] = target;
prepare();
callback(true);
@ -273,174 +258,211 @@ function _easeActorProperty(actor, propName, target, params) {
}
let pspec = actor.find_property(propName);
let transition = new Clutter.PropertyTransition(Object.assign({
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));
},
params
)
);
actor.add_transition(propName, transition);
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 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;
}
// 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();
log("initializing...");
// Add some bindings to the global JS namespace
globalThis.log = _loggingFunc;
// 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._ = Gettext.gettext;
globalThis.C_ = Gettext.pgettext;
globalThis.ngettext = Gettext.ngettext;
globalThis.N_ = s => s;
globalThis.log = _loggingFunc;
GObject.gtypeNameBasedOnJSPath = true;
globalThis._ = Gettext.gettext;
globalThis.C_ = Gettext.pgettext;
globalThis.ngettext = Gettext.ngettext;
globalThis.N_ = (s) => s;
// Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout);
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}` : ""}`);
}
};
_patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
GObject.gtypeNameBasedOnJSPath = true;
let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
Clutter.Actor.prototype.set_easing_duration = function (msecs) {
// 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) {
};
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) {
Clutter.Actor.prototype.ease = function (props) {
_easeActor(this, props);
};
Clutter.Actor.prototype.ease_property = function (propName, target, params) {
};
Clutter.Actor.prototype.ease_property = function (propName, target, params) {
_easeActorProperty(this, propName, target, params);
};
St.Adjustment.prototype.ease = function (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);
};
_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[Symbol.iterator] = function* () {
for (let c = this.get_first_child(); c; c = c.get_next_sibling()) yield c;
};
Clutter.Actor.prototype.toString = function () {
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', {
};
// 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);
}
Gio._LocalFilePrototype.touch_async = function (callback) {
Shell.util_touch_file_async(this, callback);
};
Gio._LocalFilePrototype.touch_finish = function (result) {
};
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) {
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 () {
/**
* @param {unknown} obj
* @returns {obj is {actor: unknown}}
*/
function hasActor(obj) {
let actorObj = /** @type {{actor?: unknown}} */ (obj);
return "actor" in actorObj;
}
let origToString = Object.prototype.toString;
Object.prototype.toString = function () {
let base = origToString.call(this);
try {
if ('actor' in this && this.actor instanceof Clutter.Actor)
if (hasActor(this) && this.actor instanceof Clutter.Actor)
return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
else
return base;
else return base;
} catch (e) {
return base;
}
};
};
// Override to clear our own timezone cache as well
const origClearDateCaches = System.clearDateCaches;
System.clearDateCaches = function () {
// 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();
// 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,
let dt = GLib.DateTime.new(
_localTimeZone,
this.getFullYear(),
this.getMonth() + 1,
this.getDate(),
this.getHours(),
this.getMinutes(),
this.getSeconds());
return dt?.format(format) ?? '';
};
this.getSeconds()
);
return dt?.format(format) ?? "";
};
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
if (slowdownEnv) {
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;
String.prototype.format = Format.format;
Math.clamp = function (x, lower, upper) {
return Math.min(Math.max(x, lower), upper);
};
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;
String.prototype.format = Format.format;
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) {
export function adjustAnimationTime(msecs) {
let settings = St.Settings.get();
if (!settings.enable_animations)
return 1;
if (!settings.enable_animations) return 1;
return settings.slow_down_factor * msecs;
}

View file

@ -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,9 +23,9 @@ 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' });

View file

@ -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;
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';
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 * 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);
// if (extensionModule.init) {
// try {
// extensionState = extensionModule.init(extension);
// } catch (e) {
// this.logExtensionError(uuid, e);
// return false;
// }
// }
// if (!extensionState)
// extensionState = extensionModule;
// extension.stateObj = extensionState;
// extension.state = ExtensionState.DISABLED;
// this.emit('extension-loaded', uuid);
return false;
}
}
if (!extensionState)
extensionState = extensionModule;
extension.stateObj = extensionState;
extension.state = ExtensionState.DISABLED;
this.emit('extension-loaded', uuid);
return true;
}
_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() {

View file

@ -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();

View file

@ -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');

View file

@ -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);
});

View file

@ -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,18 +1314,17 @@ 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() {

View file

@ -1,9 +1,17 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, 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 Gtk from 'gi://Gtk';
import Meta from 'gi://Meta';
import Pango from 'gi://Pango';
import Shell from 'gi://Shell';
import St from 'gi://St';
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
const PermissionStore = imports.misc.permissionStore;
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,

View file

@ -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.");
});

View file

@ -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");

View file

@ -1,16 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported KeyboardManager */
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';
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 * 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();

View file

@ -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();

View file

@ -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),

View file

@ -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());

View file

@ -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;
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';
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 * 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));
}

View file

@ -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) {
@ -405,17 +419,6 @@ var Magnifier = class Magnifier extends Signals.EventEmitter {
this._crossHairs.setOpacity(opacity * 255);
}
/**
* 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.
@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -3,32 +3,38 @@
NotificationApplicationPolicy, Source, SourceActor,
SystemNotificationSource, MessageTray */
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 Calendar = imports.ui.calendar;
const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
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() {

View file

@ -1,17 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModalDialog */
const { Atk, Clutter, GObject, Shell, St } = imports.gi;
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';
const Dialog = imports.ui.dialog;
const Layout = imports.ui.layout;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
import * as Dialog from './dialog.js';
import * as Layout from './layout.js';
import * as Lightbox from './lightbox.js';
import Main from './main.js';
var OPEN_AND_CLOSE_TIME = 100;
var FADE_OUT_DIALOG_TIME = 1000;
export let OPEN_AND_CLOSE_TIME = 100;
export let FADE_OUT_DIALOG_TIME = 1000;
var State = {
/** @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)),
});
}
});

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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',

View file

@ -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()) {

View file

@ -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;
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 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 * 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) {

View file

@ -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;
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';
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Layout = imports.ui.layout;
import Main from './main.js';
import * as PopupMenu from './popupMenu.js';
import * as Layout from './layout.js';
const { loadInterfaceXML } = imports.misc.fileUtils;
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();

View file

@ -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

View file

@ -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;
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';
const Animation = imports.ui.animation;
const { AppMenu } = imports.ui.appMenu;
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;

View file

@ -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({

View file

@ -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();

View file

@ -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));

View file

@ -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;
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';
const BoxPointer = imports.ui.boxpointer;
const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
import * as BoxPointer from './boxpointer.js';
import * as GrabHelper from './grabHelper.js';
import Main from './main.js';
var Ornament = {
/** @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,8 +281,17 @@ 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 {
/**
* @param {PopupMenuItemParams & PopupBaseMenuItemParams} [params]
*/
_init(text, params) {
super._init(params);
@ -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,7 +376,7 @@ 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) {
@ -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;
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,

View file

@ -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);

View file

@ -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;

Some files were not shown because too many files have changed in this diff Show more