Legatura chiave estensione gnome shell


11

Qual è il modo più semplice per associare (globalmente) una combinazione di tasti (ad es. <Super>+A) A una funzione in un'estensione della shell di gnome?

Ispezionando un paio di estensioni, ho incontrato il seguente codice:

global.display.add_keybinding('random-name',
                              new Gio.Settings({schema: 'org.gnome.shell.keybindings'}),
                              Meta.KeyBindingFlags.NONE,
                              function() { /* ... some code */ });

Comprendo che la combinazione di chiavi è specificata dal parametro dello schema e che è possibile creare un file XML che descriva la combinazione. C'è un modo più semplice per farlo?


Se si sta creando un'estensione della shell GNOME, probabilmente si otterrebbero risposte migliori su http://stackoverflow.com/ . Contrassegna l'attenzione del moderatore e dovrebbero migrare la tua domanda.
NobleUplift,

Risposte:


5

TL; DR

Ecco una lezione:

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)
        }
    }
})

Ed è così che lo usi:

let keyManager = new KeyManager()
keyManager.listenFor("<ctrl><shift>a", function(){
    log("Hot keys are working!!!")
})

Avrai bisogno di importazioni:

const Lang = imports.lang
const Meta = imports.gi.Meta
const Shell = imports.gi.Shell
const Main = imports.ui.main

Per interrompere l'ascolto:

for (let it of keyManager.grabbers) {
    global.display.ungrab_accelerator(it[1].action)
    Main.wm.allowKeybinding(it[1].name, Shell.ActionMode.NONE)
}

Spiegazione

Potrei essere terribilmente sbagliato, ma questo è quello che ho capito negli ultimi due giorni.

Innanzitutto è Mutter il responsabile dell'ascolto dei tasti di scelta rapida. Mutter è un framework per la creazione di Window Manager, non è un window manager stesso. Gnome Shell ha una classe scritta in JS e chiamata "Window Manager" - questo è il vero Window Manager che usa Mutter internamente per fare tutte le cose di basso livello. Mutter ha un oggetto MetaDisplay. Questo è l'oggetto che usi per richiedere l'ascolto di un tasto di scelta rapida. Ma! Ma Mutter richiederà a Window Manager di approvare l'uso di questo tasto di scelta rapida. Quindi cosa succede quando si preme il tasto di scelta rapida? - MetaDisplay genera l'evento "filtro-legatura". - Window Manager in Gnome Shell verifica se questo tasto di scelta rapida ha potuto essere elaborato. - Window Manager restituisce il valore appropriato a MetaDisplay - Se è consentito elaborare questo tasto di scelta rapida, MetaDisplay genera l'evento "attivato dall'acceleratore"


Ho testato questo codice solo in Gnome 3.22
p2t2p il

Questa è una risposta fantastica, grazie mille per averlo condiviso.
andy.holmes,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.