diff --git a/js/dbusServices/extensions/css/application.css b/js/dbusServices/extensions/css/application.css new file mode 100644 index 000000000..06914ea3c --- /dev/null +++ b/js/dbusServices/extensions/css/application.css @@ -0,0 +1,2 @@ +.expander-frame > * { border-top-width: 0; } +.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; } diff --git a/js/dbusServices/extensions/extensionsService.js b/js/dbusServices/extensions/extensionsService.js index 9ea07df45..482373846 100644 --- a/js/dbusServices/extensions/extensionsService.js +++ b/js/dbusServices/extensions/extensionsService.js @@ -1,7 +1,9 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- /* exported ExtensionsService */ -const { Gio, GLib } = imports.gi; +const { Gdk, Gio, GLib, GObject, Gtk } = imports.gi; + +const ExtensionUtils = imports.misc.extensionUtils; const { loadInterfaceXML } = imports.misc.fileUtils; const { ServiceImplementation } = imports.dbusService; @@ -108,10 +110,25 @@ var ExtensionsService = class extends ServiceImplementation { } OpenExtensionPrefsAsync(params, invocation) { - this._proxy.OpenExtensionPrefsRemote(...params, (res, error) => { + const [uuid, parentWindow_, options] = params; + + this._proxy.GetExtensionInfoRemote(uuid, (res, error) => { if (this._handleError(invocation, error)) return; + const [serialized] = res; + const extension = ExtensionUtils.deserializeExtension(serialized); + + const window = new ExtensionPrefsDialog(extension); + + if (options.modal) + window.modal = options.modal.get_boolean(); + + window.connect('destroy', () => this.release()); + this.hold(); + + window.show(); + invocation.return_value(null); }); } @@ -125,3 +142,124 @@ var ExtensionsService = class extends ServiceImplementation { }); } }; + +var ExtensionPrefsDialog = GObject.registerClass({ + GTypeName: 'ExtensionPrefsDialog', + Template: 'resource:///org/gnome/Shell/Extensions/ui/extension-prefs-dialog.ui', + InternalChildren: [ + 'headerBar', + 'stack', + 'expander', + 'expanderArrow', + 'revealer', + 'errorView', + ], +}, class ExtensionPrefsDialog extends Gtk.Window { + _init(extension) { + super._init(); + + this._uuid = extension.uuid; + this._url = extension.metadata.url || ''; + + this._headerBar.title = extension.metadata.name; + + this._actionGroup = new Gio.SimpleActionGroup(); + this.insert_action_group('win', this._actionGroup); + + this._initActions(); + this._addCustomStylesheet(); + + this._gesture = new Gtk.GestureMultiPress({ + widget: this._expander, + button: 0, + exclusive: true, + }); + + this._gesture.connect('released', (gesture, nPress) => { + if (nPress === 1) + this._revealer.reveal_child = !this._revealer.reveal_child; + }); + + this._revealer.connect('notify::reveal-child', () => { + this._expanderArrow.icon_name = this._revealer.reveal_child + ? 'pan-down-symbolic' + : 'pan-end-symbolic'; + }); + + try { + ExtensionUtils.installImporter(extension); + + // give extension prefs access to their own extension object + ExtensionUtils.getCurrentExtension = () => extension; + + const prefsModule = extension.imports.prefs; + prefsModule.init(extension.metadata); + + const widget = prefsModule.buildPrefsWidget(); + this._stack.add(widget); + this._stack.visible_child = widget; + } catch (e) { + this._setError(e); + } + } + + _setError(exc) { + this._errorView.buffer.text = `${exc}\n\nStack trace:\n`; + // Indent stack trace. + this._errorView.buffer.text += + exc.stack.split('\n').map(line => ` ${line}`).join('\n'); + + // markdown for pasting in gitlab issues + let lines = [ + `The settings of extension ${this._uuid} had an error:`, + '```', + `${exc}`, + '```', + '', + 'Stack trace:', + '```', + exc.stack.replace(/\n$/, ''), // stack without trailing newline + '```', + '', + ]; + this._errorMarkdown = lines.join('\n'); + this._actionGroup.lookup('copy-error').enabled = true; + } + + _initActions() { + let action; + + action = new Gio.SimpleAction({ + name: 'copy-error', + enabled: false, + }); + action.connect('activate', () => { + const clipboard = Gtk.Clipboard.get_default(this.get_display()); + clipboard.set_text(this._errorMarkdown, -1); + }); + this._actionGroup.add_action(action); + + action = new Gio.SimpleAction({ + name: 'show-url', + enabled: this._url !== '', + }); + action.connect('activate', () => { + Gio.AppInfo.launch_default_for_uri(this._url, + this.get_display().get_app_launch_context()); + }); + this._actionGroup.add_action(action); + } + + _addCustomStylesheet() { + let provider = new Gtk.CssProvider(); + let uri = 'resource:///org/gnome/Shell/Extensions/css/application.css'; + try { + provider.load_from_file(Gio.File.new_for_uri(uri)); + } catch (e) { + logError(e, 'Failed to add application style'); + } + Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } +}); diff --git a/js/dbusServices/extensions/main.js b/js/dbusServices/extensions/main.js index 8f139a64f..9cc4bc5e3 100644 --- a/js/dbusServices/extensions/main.js +++ b/js/dbusServices/extensions/main.js @@ -1,9 +1,18 @@ /* exported main */ +imports.gi.versions.Gdk = '3.0'; +imports.gi.versions.Gtk = '3.0'; + +const { Gtk } = imports.gi; +const pkg = imports.package; + const { DBusService } = imports.dbusService; const { ExtensionsService } = imports.extensionsService; function main() { + Gtk.init(null); + pkg.initFormat(); + const service = new DBusService( 'org.gnome.Shell.Extensions', new ExtensionsService()); diff --git a/js/extensionPrefs/data/ui/extension-prefs-dialog.ui b/js/dbusServices/extensions/ui/extension-prefs-dialog.ui similarity index 100% rename from js/extensionPrefs/data/ui/extension-prefs-dialog.ui rename to js/dbusServices/extensions/ui/extension-prefs-dialog.ui diff --git a/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml index 7bbcdab11..7436f2e89 100644 --- a/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml +++ b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml @@ -6,6 +6,12 @@ dbusService.js misc/config.js + misc/extensionUtils.js misc/fileUtils.js + + + css/application.css + ui/extension-prefs-dialog.ui + diff --git a/js/extensionPrefs/data/css/application.css b/js/extensionPrefs/data/css/application.css index 5641c5d23..37105d081 100644 --- a/js/extensionPrefs/data/css/application.css +++ b/js/extensionPrefs/data/css/application.css @@ -9,6 +9,3 @@ } image.warning { color: @warning_color; } - -.expander-frame > * { border-top-width: 0; } -.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; } diff --git a/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml b/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml index de65e0823..659c03ffc 100644 --- a/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml +++ b/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml @@ -5,7 +5,6 @@ dbus-interfaces/org.gnome.Shell.Extensions.xml - ui/extension-prefs-dialog.ui ui/extension-row.ui ui/extensions-window.ui diff --git a/js/extensionPrefs/js/main.js b/js/extensionPrefs/js/main.js index b96319c87..fd7605157 100644 --- a/js/extensionPrefs/js/main.js +++ b/js/extensionPrefs/js/main.js @@ -85,7 +85,6 @@ var ExtensionsWindow = GObject.registerClass({ _init(params) { super._init(params); - this._prefsDialog = null; this._updatesCheckId = 0; this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment); @@ -152,16 +151,9 @@ var ExtensionsWindow = GObject.registerClass({ } openPrefs(uuid) { - if (this._prefsDialog) - return; - - let row = this._findExtensionRow(uuid); - this._prefsDialog = new ExtensionPrefsDialog(row); - this._prefsDialog.set({ transient_for: this, modal: true }); - - this._prefsDialog.connect('destroy', () => (this._prefsDialog = null)); - - this._prefsDialog.show(); + this._shellProxy.OpenExtensionPrefsRemote(uuid, + '', + { modal: new GLib.Variant('b', true) }); } _showAbout() { @@ -467,119 +459,6 @@ var ExtensionRow = GObject.registerClass({ _canToggle() { return this._extension.canChange; } - - get prefsModule() { - // give extension prefs access to their own extension object - ExtensionUtils.getCurrentExtension = () => this._extension; - - if (!this._prefsModule) { - ExtensionUtils.installImporter(this._extension); - - this._prefsModule = this._extension.imports.prefs; - this._prefsModule.init(this._extension.metadata); - } - - return this._prefsModule; - } -}); - -var ExtensionPrefsDialog = GObject.registerClass({ - GTypeName: 'ExtensionPrefsDialog', - Template: 'resource:///org/gnome/Extensions/ui/extension-prefs-dialog.ui', - InternalChildren: [ - 'headerBar', - 'stack', - 'expander', - 'expanderArrow', - 'revealer', - 'errorView', - ], -}, class ExtensionPrefsDialog extends Gtk.Window { - _init(extension) { - super._init(); - - this._uuid = extension.uuid; - this._url = extension.url; - - this._headerBar.title = extension.name; - - this._actionGroup = new Gio.SimpleActionGroup(); - this.insert_action_group('win', this._actionGroup); - - this._initActions(); - - this._gesture = new Gtk.GestureMultiPress({ - widget: this._expander, - button: 0, - exclusive: true, - }); - - this._gesture.connect('released', (gesture, nPress) => { - if (nPress === 1) - this._revealer.reveal_child = !this._revealer.reveal_child; - }); - - this._revealer.connect('notify::reveal-child', () => { - this._expanderArrow.icon_name = this._revealer.reveal_child - ? 'pan-down-symbolic' - : 'pan-end-symbolic'; - }); - - try { - const widget = extension.prefsModule.buildPrefsWidget(); - this._stack.add(widget); - this._stack.visible_child = widget; - } catch (e) { - this._setError(e); - } - } - - _setError(exc) { - this._errorView.buffer.text = '%s\n\nStack trace:\n'.format(exc); - // Indent stack trace. - this._errorView.buffer.text += - exc.stack.split('\n').map(line => ' %s'.format(line)).join('\n'); - - // markdown for pasting in gitlab issues - let lines = [ - 'The settings of extension %s had an error:'.format(this._uuid), - '```', // '`' (xgettext throws up on odd number of backticks) - exc.toString(), - '```', // '`' - '', - 'Stack trace:', - '```', // '`' - exc.stack.replace(/\n$/, ''), // stack without trailing newline - '```', // '`' - '', - ]; - this._errorMarkdown = lines.join('\n'); - this._actionGroup.lookup('copy-error').enabled = true; - } - - _initActions() { - let action; - - action = new Gio.SimpleAction({ - name: 'copy-error', - enabled: false, - }); - action.connect('activate', () => { - const clipboard = Gtk.Clipboard.get_default(this.get_display()); - clipboard.set_text(this._errorMarkdown, -1); - }); - this._actionGroup.add_action(action); - - action = new Gio.SimpleAction({ - name: 'show-url', - enabled: this._url !== '', - }); - action.connect('activate', () => { - Gio.AppInfo.launch_default_for_uri(this._url, - this.get_display().get_app_launch_context()); - }); - this._actionGroup.add_action(action); - } }); function initEnvironment() { diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index 983a88712..2b6b2ae96 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -1,7 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- /* exported GnomeShell, ScreenSaverDBus */ -const { Gio, GLib, Meta, Shell } = imports.gi; +const { Gio, GLib, Meta } = imports.gi; const Config = imports.misc.config; const ExtensionDownloader = imports.ui.extensionDownloader; @@ -315,13 +315,18 @@ var GnomeShellExtensions = class { this.OpenExtensionPrefs(uuid, '', {}); } - OpenExtensionPrefs(uuid, _parentWindow, _options) { - let appSys = Shell.AppSystem.get_default(); - let app = appSys.lookup_app('org.gnome.Extensions.desktop'); - let info = app.get_app_info(); - let timestamp = global.display.get_current_time_roundtrip(); - info.launch_uris([`extension:///${uuid}`], - global.create_app_launch_context(timestamp, -1)); + OpenExtensionPrefs(uuid, parentWindow, options) { + Gio.DBus.session.call( + 'org.gnome.Shell.Extensions', + '/org/gnome/Shell/Extensions', + 'org.gnome.Shell.Extensions', + 'OpenExtensionPrefs', + new GLib.Variant('(ssa{sv})', [uuid, parentWindow, options]), + null, + Gio.DBusCallFlags.NONE, + -1, + null, + (conn, res) => conn.call_finish(res)); } ReloadExtension(uuid) { diff --git a/po/POTFILES.in b/po/POTFILES.in index ba8a5b13b..92cdaf5ce 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,10 +4,10 @@ data/50-gnome-shell-system.xml data/org.gnome.Shell.desktop.in.in data/org.gnome.shell.gschema.xml.in data/org.gnome.Shell.PortalHelper.desktop.in.in +js/dbusServices/extensions/ui/extension-prefs-dialog.ui js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in js/extensionPrefs/js/main.js -js/extensionPrefs/data/ui/extension-prefs-dialog.ui js/extensionPrefs/data/ui/extension-row.ui js/extensionPrefs/data/ui/extensions-window.ui js/gdm/authPrompt.js