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;
+}