Binding Kunci Ekstensi Gnome Shell

11

Apa cara paling sederhana untuk (secara global) mengikat kombinasi kunci (mis. <Super>+A ) ke suatu fungsi dalam ekstensi shell gnome?

Memeriksa beberapa ekstensi, saya menemukan kode berikut:

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

Saya mengerti bahwa kombinasi tombol ditentukan oleh parameter skema, dan dimungkinkan untuk membuat file XML yang menggambarkan kombinasi tersebut. Apakah ada cara yang lebih sederhana untuk melakukan ini?

Mark Jones
sumber
Jika Anda membuat ekstensi shell GNOME maka Anda mungkin akan mendapatkan respons yang lebih baik http://stackoverflow.com/ . Tandai untuk perhatian moderator dan mereka harus memigrasikan pertanyaan Anda.
NobleUplift

Jawaban:

5

TL; DR

Ini kelasnya:

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

Dan itulah cara Anda menggunakannya:

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

Anda akan membutuhkan impor:

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

Untuk berhenti mendengarkan:

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

Penjelasan

Saya mungkin sangat salah, tetapi itulah yang saya temukan dalam beberapa hari terakhir.

Pertama-tama adalah Mutter yang bertanggung jawab untuk mendengarkan hotkey. Mutter adalah kerangka kerja untuk membuat Window Managers, itu bukan window manager itu sendiri. Gnome Shell memiliki kelas yang ditulis dalam JS dan disebut "Window Manager" - ini adalah Window Manager nyata yang menggunakan Mutter secara internal untuk melakukan semua hal tingkat rendah. Mutter memiliki objek MetaDisplay. Ini adalah objek yang Anda gunakan untuk meminta mendengarkan hotkey. Tapi! Tetapi Mutter akan meminta Window Manager untuk menyetujui penggunaan hotkey ini. Jadi apa yang terjadi ketika hotkey ditekan? - MetaDisplay menghasilkan 'filter-keybinding' acara. - Window Manager di Gnome Shell memeriksa apakah hotkey ini diizinkan untuk diproses. - Window Manager mengembalikan nilai yang sesuai ke MetaDisplay - Jika diizinkan untuk memproses hotkey ini, MetaDisplay menghasilkan acara 'akselerator-diaktifkan' - Ekstensi Anda harus mendengarkan acara itu dan mencari tahu dengan action id hotkey mana yang diaktifkan.

p2t2p
sumber
Saya telah menguji kode ini hanya di Gnome 3.22
p2t2p
Ini jawaban yang fantastis, terima kasih banyak sudah berbagi ini.
andy.holmes
1

gconf-editor mungkin melakukan apa yang Anda inginkan: link

Andrea Gottardi
sumber