diff --git a/appIcons.js b/appIcons.js index 5fe209b..4019d66 100644 --- a/appIcons.js +++ b/appIcons.js @@ -1739,60 +1739,99 @@ var MyShowAppsIconMenu = Utils.defineClass({ _dtpRedisplay: function() { this.removeAll(); + + // Only add menu entries for commands that exist in path + function _appendItem(obj, info) { + if (Utils.checkIfCommandExists(info.cmd[0])) { + let item = obj._appendMenuItem(_(info.title)); - if (this.sourceActor != Main.layoutManager.dummyCursor) { - let powerSettingsMenuItem = this._appendMenuItem(_('Power options')); - powerSettingsMenuItem.connect('activate', function () { - Util.spawn(['gnome-control-center', 'power']); + item.connect('activate', function() { + Util.spawn(info.cmd); + }); + return item; + } + + return null; + } + + function _appendList(obj, commandList, titleList) { + if (commandList.length != titleList.length) { + return; + } + + for (var entry = 0; entry < commandList.length; entry++) { + _appendItem(obj, { + title: titleList[entry], + cmd: commandList[entry].split(' ') + }); + } + } + + if (this.sourceActor != Main.layoutManager.dummyCursor) { + _appendItem(this, { + title: 'Power options', + cmd: ['gnome-control-center', 'power'] }); - let logsMenuItem = this._appendMenuItem(_('Event logs')); - logsMenuItem.connect('activate', function () { - Util.spawn(['gnome-logs']); + _appendItem(this, { + title: 'Event logs', + cmd: ['gnome-logs'] }); - let systemSettingsMenuItem = this._appendMenuItem(_('System')); - systemSettingsMenuItem.connect('activate', function () { - Util.spawn(['gnome-control-center', 'info-overview']); + _appendItem(this, { + title: 'System', + cmd: ['gnome-control-center', 'info-overview'] }); - let devicesSettingsMenuItem = this._appendMenuItem(_('Device Management')); - devicesSettingsMenuItem.connect('activate', function () { - Util.spawn(['gnome-control-center', 'display']); + _appendItem(this, { + title: 'Device Management', + cmd: ['gnome-control-center', 'display'] }); - let disksMenuItem = this._appendMenuItem(_('Disk Management')); - disksMenuItem.connect('activate', function () { - Util.spawn(['gnome-disks']); + _appendItem(this, { + title: 'Disk Management', + cmd: ['gnome-disks'] }); + _appendList( + this, + Me.settings.get_strv('show-apps-button-context-menu-commands'), + Me.settings.get_strv('show-apps-button-context-menu-titles') + ) + this._appendSeparator(); } - let terminalMenuItem = this._appendMenuItem(_('Terminal')); - terminalMenuItem.connect('activate', function () { - Util.spawn(['gnome-terminal']); + _appendItem(this, { + title: 'Terminal', + cmd: ['gnome-terminal'] }); - let systemMonitorMenuItem = this._appendMenuItem(_('System monitor')); - systemMonitorMenuItem.connect('activate', function () { - Util.spawn(['gnome-system-monitor']); + _appendItem(this, { + title: 'System monitor', + cmd: ['gnome-system-monitor'] }); - let filesMenuItem = this._appendMenuItem(_('Files')); - filesMenuItem.connect('activate', function () { - Util.spawn(['nautilus']); + _appendItem(this, { + title: 'Files', + cmd: ['nautilus'] }); - let extPrefsMenuItem = this._appendMenuItem(_('Extensions')); - extPrefsMenuItem.connect('activate', function () { - Util.spawn(["gnome-shell-extension-prefs"]); + _appendItem(this, { + title: 'Extensions', + cmd: ['gnome-shell-extension-prefs'] }); - let gsSettingsMenuItem = this._appendMenuItem(_('Settings')); - gsSettingsMenuItem.connect('activate', function () { - Util.spawn(['gnome-control-center', 'wifi']); - }); + _appendItem(this, { + title: 'Settings', + cmd: ['gnome-control-center', 'wifi'] + }); + + _appendList( + this, + Me.settings.get_strv('panel-context-menu-commands'), + Me.settings.get_strv('panel-context-menu-titles') + ) this._appendSeparator(); @@ -1823,4 +1862,4 @@ adjustMenuRedisplay(MyShowAppsIconMenu.prototype); function adjustMenuRedisplay(menuProto) { menuProto[menuRedisplayFunc] = function() { this._dtpRedisplay(menuRedisplayFunc) }; -} \ No newline at end of file +} diff --git a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml index acbd651..d40ca56 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -372,6 +372,26 @@ Animate Show Applications from the desktop Animate Show Applications from the desktop + + [] + Show Apps button context menu commands + Commands to add to the Show Apps button right click menu + + + [] + Show Apps button context menu titles + Titles for commands added to Show Apps button right click menu + + + [] + Panel context menu commands + Commands to add to the panel right click menu + + + [] + Panel context menu titles + Titles for commands added to panel right click menu + false Show activities button @@ -1186,7 +1206,7 @@ Show progress bar on app icon Whether to show progress bar overlay on app icon, for supported applications. - + true Show badge count on app icon Whether to show badge count overlay on app icon, for supported applications. diff --git a/utils.js b/utils.js index 8bd10b4..57f6a54 100644 --- a/utils.js +++ b/utils.js @@ -26,6 +26,7 @@ const Config = imports.misc.config; const GdkPixbuf = imports.gi.GdkPixbuf const Gi = imports._gi; const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; const GObject = imports.gi.GObject; const Gtk = imports.gi.Gtk; const Meta = imports.gi.Meta; @@ -922,4 +923,29 @@ var drawRoundedLine = function(cr, x, y, width, height, isRoundLeft, isRoundRigh if (stroke != null) cr.setSource(stroke); cr.stroke(); -} \ No newline at end of file +} + +/** + * Check if an app exists in the system. + */ +var checkedCommandsMap = new Map(); + +function checkIfCommandExists(app) { + let answer = checkedCommandsMap.get(app); + if (answer === undefined) { + // Command is a shell built in, use shell to call it. + // Quotes around app value are important. They let command operate + // on the whole value, instead of having shell interpret it. + let cmd = "sh -c 'command -v \"" + app + "\"'"; + try { + let out = GLib.spawn_command_line_sync(cmd); + // out contains 1: stdout, 2: stderr, 3: exit code + answer = out[3] == 0; + } catch { + answer = false; + } + + checkedCommandsMap.set(app, answer); + } + return answer; +}