TL; DR
Ось клас:
KeyManager: new Lang.Class({
Name: 'MyKeyManager',
_init: function() {
this.grabbers = new Map()
global.display.connect(
'accelerator-activated',
Lang.bind(this, function(display, action, deviceId, timestamp){
log('Accelerator Activated: [display={}, action={}, deviceId={}, timestamp={}]',
display, action, deviceId, timestamp)
this._onAccelerator(action)
}))
},
listenFor: function(accelerator, callback){
log('Trying to listen for hot key [accelerator={}]', accelerator)
let action = global.display.grab_accelerator(accelerator)
if(action == Meta.KeyBindingAction.NONE) {
log('Unable to grab accelerator [binding={}]', accelerator)
} else {
log('Grabbed accelerator [action={}]', action)
let name = Meta.external_binding_name_for_action(action)
log('Received binding name for action [name={}, action={}]',
name, action)
log('Requesting WM to allow binding [name={}]', name)
Main.wm.allowKeybinding(name, Shell.ActionMode.ALL)
this.grabbers.set(action, {
name: name,
accelerator: accelerator,
callback: callback,
action: action
})
}
},
_onAccelerator: function(action) {
let grabber = this.grabbers.get(action)
if(grabber) {
this.grabbers.get(action).callback()
} else {
log('No listeners [action={}]', action)
}
}
})
І ось як ви це використовуєте:
let keyManager = new KeyManager()
keyManager.listenFor("<ctrl><shift>a", function(){
log("Hot keys are working!!!")
})
Вам знадобиться імпорт:
const Lang = imports.lang
const Meta = imports.gi.Meta
const Shell = imports.gi.Shell
const Main = imports.ui.main
Щоб перестати слухати:
for (let it of keyManager.grabbers) {
global.display.ungrab_accelerator(it[1].action)
Main.wm.allowKeybinding(it[1].name, Shell.ActionMode.NONE)
}
Пояснення
Я можу страшенно помилятися, але це те, що я з'ясував за останні пару днів.
Перш за все, саме Муттер відповідає за прослуховування гарячих клавіш. Mutter - це основа для створення менеджерів вікон, це не сам менеджер вікон. У Gnome Shell є клас, написаний на JS і який називається "Window Manager" - це справжній Менеджер вікон, який використовує Mutter внутрішньо, щоб виконувати всі речі низького рівня. Mutter має об'єкт MetaDisplay. Це об'єкт, який ви використовуєте для запиту прослуховування гарячої клавіші. Але! Але Mutter зажадає, щоб менеджер вікон схвалив використання цієї гарячої клавіші. Отже, що відбувається при натисканні швидкої клавіші? - MetaDisplay генерує подію 'фільтр-прив'язка клавіш'. - Менеджер вікон у Gnome Shell перевіряє, чи дозволено обробляти цю гарячу клавішу. - Менеджер вікон повертає відповідне значення для MetaDisplay - Якщо йому дозволено обробляти цю гарячу клавішу, MetaDisplay генерує події 'accelerator-actived'