f6b4b96737
We can use that newer method where we don't care about the actual position of an element inside the array. (Array.includes() and Array.indexOf() do behave differently in edge cases, for example in the handling of NaN, but those don't matter to us) https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/152
157 lines
5.2 KiB
JavaScript
157 lines
5.2 KiB
JavaScript
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
|
|
|
|
const Dialog = imports.ui.dialog;
|
|
const ModalDialog = imports.ui.modalDialog;
|
|
const PermissionStore = imports.misc.permissionStore;
|
|
|
|
const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
|
|
|
|
const APP_WHITELIST = ['gnome-control-center.desktop'];
|
|
const APP_PERMISSIONS_TABLE = 'gnome';
|
|
const APP_PERMISSIONS_ID = 'shortcuts-inhibitor';
|
|
const GRANTED = 'GRANTED';
|
|
const DENIED = 'DENIED';
|
|
|
|
var DialogResponse = Meta.InhibitShortcutsDialogResponse;
|
|
|
|
var InhibitShortcutsDialog = GObject.registerClass({
|
|
Implements: [Meta.InhibitShortcutsDialog],
|
|
Properties: {
|
|
'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog)
|
|
}
|
|
}, class InhibitShortcutsDialog extends GObject.Object {
|
|
_init(window) {
|
|
super._init();
|
|
this._window = window;
|
|
|
|
this._dialog = new ModalDialog.ModalDialog();
|
|
this._buildLayout();
|
|
}
|
|
|
|
get window() {
|
|
return this._window;
|
|
}
|
|
|
|
set window(window) {
|
|
this._window = window;
|
|
}
|
|
|
|
get _app() {
|
|
let windowTracker = Shell.WindowTracker.get_default();
|
|
return windowTracker.get_window_app(this._window);
|
|
}
|
|
|
|
_getRestoreAccel() {
|
|
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));
|
|
}
|
|
|
|
_shouldUsePermStore() {
|
|
return this._app && !this._app.is_window_backed();
|
|
}
|
|
|
|
_saveToPermissionStore(grant) {
|
|
if (!this._shouldUsePermStore() || this._permStore == null)
|
|
return;
|
|
|
|
let permissions = {};
|
|
permissions[this._app.get_id()] = [grant];
|
|
let data = GLib.Variant.new('av', {});
|
|
|
|
this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
|
|
true,
|
|
APP_PERMISSIONS_ID,
|
|
permissions,
|
|
data,
|
|
(result, error) => {
|
|
if (error != null)
|
|
log(error.message);
|
|
});
|
|
}
|
|
|
|
_buildLayout() {
|
|
let name = this._app ? this._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 };
|
|
|
|
let restoreAccel = this._getRestoreAccel();
|
|
if (restoreAccel)
|
|
contentParams.subtitle =
|
|
/* Translators: %s is a keyboard shortcut like "Super+x" */
|
|
_("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._saveToPermissionStore(DENIED);
|
|
this._emitResponse(DialogResponse.DENY);
|
|
},
|
|
key: Clutter.KEY_Escape });
|
|
|
|
this._dialog.addButton({ label: _("Allow"),
|
|
action: () => {
|
|
this._saveToPermissionStore(GRANTED);
|
|
this._emitResponse(DialogResponse.ALLOW);
|
|
},
|
|
default: true });
|
|
}
|
|
|
|
_emitResponse(response) {
|
|
this.emit('response', response);
|
|
this._dialog.close();
|
|
}
|
|
|
|
vfunc_show() {
|
|
if (this._app && APP_WHITELIST.includes(this._app.get_id())) {
|
|
this._emitResponse(DialogResponse.ALLOW);
|
|
return;
|
|
}
|
|
|
|
if (!this._shouldUsePermStore()) {
|
|
this._dialog.open();
|
|
return;
|
|
}
|
|
|
|
/* Check with the permission store */
|
|
let appId = this._app.get_id();
|
|
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
|
|
if (error) {
|
|
log(error.message);
|
|
this._dialog.open();
|
|
return;
|
|
}
|
|
|
|
this._permStore.LookupRemote(APP_PERMISSIONS_TABLE,
|
|
APP_PERMISSIONS_ID,
|
|
(res, error) => {
|
|
if (error) {
|
|
this._dialog.open();
|
|
log(error.message);
|
|
return;
|
|
}
|
|
|
|
let [permissions, data] = res;
|
|
if (permissions[appId] === undefined) // Not found
|
|
this._dialog.open();
|
|
else if (permissions[appId] == GRANTED)
|
|
this._emitResponse(DialogResponse.ALLOW);
|
|
else
|
|
this._emitResponse(DialogResponse.DENY);
|
|
});
|
|
});
|
|
}
|
|
|
|
vfunc_hide() {
|
|
this._dialog.close();
|
|
}
|
|
});
|