diff --git a/data/theme/gnome-shell-high-contrast.css b/data/theme/gnome-shell-high-contrast.css
index 2de48db50..06558143f 100644
--- a/data/theme/gnome-shell-high-contrast.css
+++ b/data/theme/gnome-shell-high-contrast.css
@@ -454,6 +454,10 @@ StScrollBar {
.extension-dialog .message-dialog-title {
color: #b2b2a9; }
+/* Inhibit-Shortcuts Dialog */
+.inhibit-shortcuts-dialog {
+ spacing: 30px; }
+
/* Network Agent Dialog */
.network-dialog-secret-table {
spacing-rows: 15px;
diff --git a/data/theme/gnome-shell-sass b/data/theme/gnome-shell-sass
index 82941c9d9..70e3ae387 160000
--- a/data/theme/gnome-shell-sass
+++ b/data/theme/gnome-shell-sass
@@ -1 +1 @@
-Subproject commit 82941c9d93a879bab99545fdf57e4bb3299a9e7f
+Subproject commit 70e3ae3873b5269e9632525d94cf72d7bdbfb07f
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index f835c6d53..d2d8c5e34 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -454,6 +454,10 @@ StScrollBar {
.extension-dialog .message-dialog-title {
color: #b2b2a9; }
+/* Inhibit-Shortcuts Dialog */
+.inhibit-shortcuts-dialog {
+ spacing: 30px; }
+
/* Network Agent Dialog */
.network-dialog-secret-table {
spacing-rows: 15px;
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 67295a4cd..b29c11a38 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -59,6 +59,7 @@
ui/grabHelper.js
ui/ibusCandidatePopup.js
ui/iconGrid.js
+ ui/inhibitShortcutsDialog.js
ui/keyboard.js
ui/layout.js
ui/lightbox.js
diff --git a/js/ui/inhibitShortcutsDialog.js b/js/ui/inhibitShortcutsDialog.js
new file mode 100644
index 000000000..db0411df9
--- /dev/null
+++ b/js/ui/inhibitShortcutsDialog.js
@@ -0,0 +1,94 @@
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const Dialog = imports.ui.dialog;
+const ModalDialog = imports.ui.modalDialog;
+
+const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
+
+var DialogResponse = Meta.InhibitShortcutsDialogResponse;
+
+var InhibitShortcutsDialog = new Lang.Class({
+ Name: 'InhibitShortcutsDialog',
+ Extends: GObject.Object,
+ Implements: [Meta.InhibitShortcutsDialog],
+ Properties: {
+ 'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog)
+ },
+
+ _init: function(window) {
+ this.parent();
+ this._window = window;
+
+ this._dialog = new ModalDialog.ModalDialog();
+ this._buildLayout();
+ },
+
+ get window() {
+ return this._window;
+ },
+
+ set window(window) {
+ this._window = window;
+ },
+
+ _getRestoreAccel: function() {
+ let settings = new Gio.Settings({ schema_id: WAYLAND_KEYBINDINGS_SCHEMA });
+ let accel = settings.get_strv('restore-shortcuts')[0] || '';
+ return Gtk.accelerator_get_label.apply(null,
+ Gtk.accelerator_parse(accel));
+ },
+
+ _buildLayout: function() {
+ let windowTracker = Shell.WindowTracker.get_default();
+ let app = windowTracker.get_window_app(this._window);
+ let name = app ? app.get_name() : this._window.title;
+
+ /* Translators: %s is an application name like "Settings" */
+ let title = name ? _("%s wants to inhibit shortcuts").format(name)
+ : _("Application wants to inhibit shortcuts");
+ let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
+
+ let contentParams = { icon, title };
+
+ /* Translators: %s is a keyboard shortcut like "Super+x" */
+ let restoreAccel = this._getRestoreAccel();
+ if (restoreAccel)
+ contentParams.subtitle =
+ _("You can restore shortcuts by pressing %s.").format(restoreAccel);
+
+ let content = new Dialog.MessageDialogContent(contentParams);
+ this._dialog.contentLayout.add_actor(content);
+
+ this._dialog.addButton({ label: _("Deny"),
+ action: () => {
+ this._emitResponse(DialogResponse.DENY);
+ },
+ key: Clutter.KEY_Escape });
+
+ this._dialog.addButton({ label: _("Allow"),
+ action: () => {
+ this._emitResponse(DialogResponse.ALLOW);
+ },
+ default: true });
+ },
+
+ _emitResponse: function(response) {
+ this.emit('response', response);
+ this._dialog.close();
+ },
+
+ vfunc_show: function() {
+ this._dialog.open();
+ },
+
+ vfunc_hide: function() {
+ this._dialog.close();
+ }
+});
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index eac388994..04599b7b5 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -14,6 +14,7 @@ const Signals = imports.signals;
const AltTab = imports.ui.altTab;
const Dialog = imports.ui.dialog;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
+const InhibitShortcutsDialog = imports.ui.inhibitShortcutsDialog;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
@@ -711,6 +712,7 @@ var WindowManager = new Lang.Class({
this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
this._shellwm.connect('create-close-dialog', Lang.bind(this, this._createCloseDialog));
+ this._shellwm.connect('create-inhibit-shortcuts-dialog', Lang.bind(this, this._createInhibitShortcutsDialog));
global.screen.connect('restacked', Lang.bind(this, this._syncStacking));
this._workspaceSwitcherPopup = null;
@@ -1976,6 +1978,10 @@ var WindowManager = new Lang.Class({
return new CloseDialog.CloseDialog(window);
},
+ _createInhibitShortcutsDialog: function (shellwm, window) {
+ return new InhibitShortcutsDialog.InhibitShortcutsDialog(window);
+ },
+
_showResizePopup: function(display, show, rect, displayW, displayH) {
if (show) {
if (!this._resizePopup)
diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c
index c047d0dde..a328d75e2 100644
--- a/src/gnome-shell-plugin.c
+++ b/src/gnome-shell-plugin.c
@@ -91,6 +91,9 @@ static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugi
static MetaCloseDialog * gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
MetaWindow *window);
+static MetaInhibitShortcutsDialog * gnome_shell_plugin_create_inhibit_shortcuts_dialog (MetaPlugin *plugin,
+ MetaWindow *window);
+
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
#define GNOME_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPlugin))
#define GNOME_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
@@ -153,6 +156,7 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
plugin_class->create_close_dialog = gnome_shell_plugin_create_close_dialog;
+ plugin_class->create_inhibit_shortcuts_dialog = gnome_shell_plugin_create_inhibit_shortcuts_dialog;
}
static void
@@ -436,3 +440,10 @@ gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
{
return _shell_wm_create_close_dialog (get_shell_wm (), window);
}
+
+static MetaInhibitShortcutsDialog *
+gnome_shell_plugin_create_inhibit_shortcuts_dialog (MetaPlugin *plugin,
+ MetaWindow *window)
+{
+ return _shell_wm_create_inhibit_shortcuts_dialog (get_shell_wm (), window);
+}
diff --git a/src/shell-wm-private.h b/src/shell-wm-private.h
index 46faae9d7..1363087ad 100644
--- a/src/shell-wm-private.h
+++ b/src/shell-wm-private.h
@@ -55,6 +55,9 @@ void _shell_wm_confirm_display_change (ShellWM *wm);
MetaCloseDialog * _shell_wm_create_close_dialog (ShellWM *wm,
MetaWindow *window);
+MetaInhibitShortcutsDialog * _shell_wm_create_inhibit_shortcuts_dialog (ShellWM *wm,
+ MetaWindow *window);
+
G_END_DECLS
#endif /* __SHELL_WM_PRIVATE_H__ */
diff --git a/src/shell-wm.c b/src/shell-wm.c
index 41ad08a09..a11e41904 100644
--- a/src/shell-wm.c
+++ b/src/shell-wm.c
@@ -34,6 +34,7 @@ enum
FILTER_KEYBINDING,
CONFIRM_DISPLAY_CHANGE,
CREATE_CLOSE_DIALOG,
+ CREATE_INHIBIT_SHORTCUTS_DIALOG,
LAST_SIGNAL
};
@@ -185,6 +186,22 @@ shell_wm_class_init (ShellWMClass *klass)
0,
NULL, NULL, NULL,
META_TYPE_CLOSE_DIALOG, 1, META_TYPE_WINDOW);
+ /**
+ * ShellWM::create-inhibit-shortcuts-dialog:
+ * @wm: The WM
+ * @window: The window to create the dialog for
+ *
+ * Creates an inhibit shortcuts dialog for the given window.
+ *
+ * Returns: (transfer full): The inhibit shortcuts dialog instance.
+ */
+ shell_wm_signals[CREATE_INHIBIT_SHORTCUTS_DIALOG] =
+ g_signal_new ("create-inhibit-shortcuts-dialog",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ META_TYPE_INHIBIT_SHORTCUTS_DIALOG, 1, META_TYPE_WINDOW);
}
void
@@ -414,6 +431,17 @@ _shell_wm_create_close_dialog (ShellWM *wm,
return dialog;
}
+MetaInhibitShortcutsDialog *
+_shell_wm_create_inhibit_shortcuts_dialog (ShellWM *wm,
+ MetaWindow *window)
+{
+ MetaInhibitShortcutsDialog *dialog;
+
+ g_signal_emit (wm, shell_wm_signals[CREATE_INHIBIT_SHORTCUTS_DIALOG], 0, window, &dialog);
+
+ return dialog;
+}
+
/**
* shell_wm_new:
* @plugin: the #MetaPlugin