How to handle keyboard events in gnome shell extensions?
Asked Answered
P

2

26

How can I add an event or other method to listen to keypresses on a gnome shell extension? e.g. show a dialog with each key press showing the pressed key?

I can not find any example. The documentation mentions a keyboard module, but with that common name searching is hard.

Class explanation
...
- General utils
   - Keyboard: Manage and define the keyboard events, etc. for gnome shell. 

(read above as a quote from the docs linked above. it is styled as code because the quote styling for some reason do not preserve line breaks in this site)

I found some extensions using the bellow code for results similar to what i'm asking, but i, again, failed to find docs for the specific classes and methods:

workViewInjections['_init'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_init', function(width, height, x, y, workspaces) {
        this._pickWorkspace = false;
        this._pickWindow = false;
        this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPress));                                                                                
        this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._onKeyRelease));
        connectedSignals.push({ obj: global.stage, id: this._keyPressEventId });
        connectedSignals.push({ obj: global.stage, id: this._keyReleaseEventId });
        });

Also, no class named keyboard anywhere there...

--

edit1: more searching... i think i may have to use the Clutter api. but again, not much examples or documentation for that. farthest i went was this

edit2: more searching. looking on the gnome shell source code, on the main ui tree, i think the answer is to use the barelly mentioned global object that is available to the extension code. e.g.

global.connect('key-press-event', function(if, i, know, the, signature){} );

Pothook answered 15/2, 2015 at 1:3 Comment(2)
relevant: askubuntu.com/questions/86840/…Pothook
found the keyboard module: git.gnome.org/browse/gnome-shell/tree/js/ui/keyboard.jsPothook
S
5

I came across this snippet in gcampax's gtk-js-app template some time ago, which may be related to what you're doing:

// Due to limitations of gobject-introspection wrt GdkEvent and GdkEventKey,
// this needs to be a signal handler
this.connect('key-press-event', Lang.bind(this, this._handleKeyPress));

and

_handleKeyPress: function(self, event) {
    return this.main_search_bar.handle_event(event);
},

I haven't had a need to use keyboard events yet, and this is Gtk in GJS, but the same limitation may be affecting gnome-shell extensions.

UPDATE

I've been doing some keybinding stuff lately, and if attaching a signal handler to the global object is working, you can do something like this:

global.display.connect("key-press-event", (widget, event, user_data) => {
    let [success, keyval] = event.get_keyval(); // integer
    let keyname = Gdk.keyval_name(keyval); // string keyname

    if (keyname === "Control_L") {
        // Dialog code or eg. this.keys_array.push("<Ctrl>");
    }
});

There's also some Shell keybinding code here and some shell-global documentation here that might give you more clues. Wish I could help more but I'm wrestling my own GJS atm ;)

ADDENDUM

There is a good answer here with an example class with informative logging, as well as a speculative explanation. I've also found this functionality is exposed over DBus which might be more convenient in some cases:

Bus Name: org.gnome.Shell -> Path: /org/gnome/Shell -> Interface: org.gnome.Shell

Relevant Methods:

  • GrabAccelerator(String accelerator, UInt32 flags) -> (UInt32 action)
  • UngrabAccelerator(UInt32 action) -> (Boolean success)

Signal:

  • AcceleratorActivate(UInt32, Dict of {String, Variant})
Scoles answered 24/7, 2017 at 4:7 Comment(5)
Interesting, the main method, ... .connect('key-press-event', ... is not mentioned on the shell-global doc.Pothook
and on the example linked, they use gobal.display.add_keybinding()... the shell-global list that property as being a Metacity display object. But searching for that term, i only find it on the shell object for gnome source comments.Pothook
Best I could find is people.gnome.org/~tthurman/docs/metacity/… MetaDisplay, but it doesn't have an add_keybinding() method.Pothook
After some pointed searching, I found an answer on superuser.stackexchange.com that gave me everything I need. I think it will probably do it for you too.Scoles
global.display.connect("key-press-event", ...) will not work because "There never was such a signal on MetaDisplay"Presignify
E
0

For me global.stage.connect("key-press-event", _handleKeyPress) did the trick

Es answered 14/1, 2020 at 22:15 Comment(1)
Doesn't work for me when I type something inside application windowsPresignify

© 2022 - 2024 — McMap. All rights reserved.