TL; DR
Voici une classe:
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)
}
}
})
Et c'est comme ça que vous l'utilisez:
let keyManager = new KeyManager()
keyManager.listenFor("<ctrl><shift>a", function(){
log("Hot keys are working!!!")
})
Vous allez avoir besoin d'importations:
const Lang = imports.lang
const Meta = imports.gi.Meta
const Shell = imports.gi.Shell
const Main = imports.ui.main
Pour arrêter d'écouter:
for (let it of keyManager.grabbers) {
global.display.ungrab_accelerator(it[1].action)
Main.wm.allowKeybinding(it[1].name, Shell.ActionMode.NONE)
}
Explication
Je me trompe peut-être terriblement, mais c'est ce que j'ai compris ces derniers jours.
Tout d'abord, c'est Mutter qui est responsable de l'écoute des raccourcis clavier. Mutter est un cadre pour créer des gestionnaires de fenêtres, ce n'est pas un gestionnaire de fenêtres lui-même. Gnome Shell a une classe écrite en JS et appelée "Window Manager" - c'est le vrai Window Manager qui utilise Mutter en interne pour faire toutes les choses de bas niveau. Mutter a un objet MetaDisplay. Il s'agit de l'objet que vous utilisez pour demander l'écoute d'un raccourci clavier. Mais! Mais Mutter demandera au gestionnaire de fenêtres d'approuver l'utilisation de ce raccourci clavier. Que se passe-t-il donc lorsque la touche de raccourci est enfoncée? - MetaDisplay génère un événement 'filtre-raccourci clavier'. - Le gestionnaire de fenêtres dans Gnome Shell vérifie si cette touche de raccourci a pu être traitée. - Le gestionnaire de fenêtres renvoie la valeur appropriée à MetaDisplay - S'il est autorisé à traiter ce raccourci clavier, MetaDisplay génère l'événement «activé par l'accélérateur»