Gnome Shell Extension Key Binding


11

¿Cuál es la forma más simple de vincular (globalmente) una combinación de teclas (por ejemplo <Super>+A) a una función en una extensión de shell gnome?

Al inspeccionar un par de extensiones, me encontré con el siguiente código:

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

Entiendo que la combinación de teclas se especifica mediante el parámetro de esquema, y ​​que es posible crear un archivo XML que describa la combinación. ¿Hay una manera más simple de hacer esto?


Si está creando una extensión de shell GNOME, probablemente obtendrá mejores respuestas en http://stackoverflow.com/ . Marque para la atención del moderador y deben migrar su pregunta.
NobleUplift

Respuestas:


5

TL; DR

Aquí hay una clase:

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

Y así es como lo usas:

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

Necesitarás importaciones:

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

Para dejar de escuchar:

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

Explicación

Podría estar terriblemente equivocado, pero eso es lo que he descubierto en los últimos días.

En primer lugar, Mutter es el responsable de escuchar las teclas de acceso rápido. Mutter es un marco para crear administradores de ventanas, no es un administrador de ventanas en sí mismo. Gnome Shell tiene una clase escrita en JS y llamada "Administrador de ventanas": este es el Administrador de ventanas real que usa Mutter internamente para hacer todas las cosas de bajo nivel. Mutter tiene un objeto MetaDisplay. Este es un objeto que utiliza para solicitar escuchar una tecla de acceso rápido. ¡Pero! Pero Mutter requerirá que Window Manager apruebe el uso de esta tecla de acceso rápido. Entonces, ¿qué sucede cuando se presiona la tecla de acceso rápido? - MetaDisplay genera el evento 'filter-keybinding'. - El Administrador de ventanas en Gnome Shell verifica si esta tecla de acceso rápido permitió ser procesada. - Window Manager devuelve el valor apropiado a MetaDisplay - Si se le permite procesar esta tecla de acceso rápido, MetaDisplay genera el evento 'acelerador-activado'


He probado este código solo en Gnome 3.22
p2t2p

Esta es una respuesta fantástica, muchas gracias por compartir esto.
andy.holmes

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.