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