reddit / emacs
Keybinding using Hyper Key
alfamadorian · 2022-04-15 23:49
I have a Moonlander keyboard with a real Hyper key, which in combination with a letter, like W, gives me: control-shift-alt-super-w (works in Gnome settings)
How can I use this in emacs to bind to a function?;)
It also seems as if emacs doesn't see it at all, when I try to see what happens when I press the combination in M-x describe-key
I'm using emacs in -nw mode (terminal)
​
​
crawsphi · 2022-04-15 23:54
The abbreviation is `H`, so for example `(global-set-key (kbd "H-x") #'execute-extended-command-for-buffer)`
alfamadorian · 2022-04-15 23:57
>(global-set-key (kbd "H-x") #'execute-extended-command-for-buffer)
Yes, I found an example and tried this: (global-set-key (kbd "H-b") 'backward-word) , but I don't think that the key combination reaches emacs at all. I suspect something is hijacking this, like xorg, gnome or Terminal
crawsphi · 2022-04-15 23:58
I see, sorry, but I can't be any help with that.
alfamadorian · 2022-04-15 23:58
Hmm, it works in gnome-terminal, so it must be the terminal I'm using;) Thanks
lebensterben · 2022-04-16 00:00
hyper key is very likely to treated as super
[deleted] · 2022-04-16 00:05
[deleted]
ieure · 2022-04-16 00:37
The Moonlander's Hyper key isn't a true hyper modifier, it sends some key combination like control-shift-alt. The USB HID has no Hyper key in it, so it's impossible for any USB or Bluetooth keyboard to send a direct hyper keycode.
If you want a true hyper key, you'll have to work around this USB limitation by remapping the key on the keyboard itself, so it only sends a single keycode instead of a modified one, and on your computer, to treat that keycode as hyper.
it's pretty easy on macOS, you can assign it to any of the right/left command/alt/control keys. I had mine on the right alt (option) key, and that worked pretty good for me.
On Linux, you have to dick around with xkb or xmodmap. It's not terrible, but it's not great, either.
On Windows, I have no idea.
I use hyper extensively, since basically nothing binds to it, so I have free reign for extensive personal keybinds.
tcbr56 · 2022-04-16 00:56
Unfortunately, hyper key and fellows super, alt may not work on text terminal.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Other-Char-Bits.html
Keys other than ASCII are quite restricted on text terminal…
https://www.gnu.org/software/emacs/manual/html_node/elisp/Ctl_002dChar-Syntax.html
bugamn · 2022-04-16 01:00
Have you tried xev to see what is reported?
noman_032018 · 2022-04-16 01:54
There are other remappers around using evdev and xinput. If the code or serial from the key is unique, you could map such based on that.
If it's not unique, some of those remappers allow targeting based on source device, which is useful for foot pedals.
edit: Hadn't noticed the terminal/nw specification. Nevermind.
noman_032018 · 2022-04-16 01:57
I'd also like if OP could post the result/output here. It may be useful to others interested in that keyboard.
nullmove · 2022-04-16 04:33
Wait what? Terminals are not supposed to see Hyper at all, Hyper is a GUI (X11) thing.
alfamadorian · 2022-04-16 07:13
I thought it worked late last night, but I have to be wrong. So weird. M-x describe-key in gnome-terminal reports this as C-M-w
nullmove · 2022-04-16 07:47
In any case, it doesn't really matter what keyboard you are using. Terminal emulators unfortunately don't support Hyper, as it's only a X11 thing and not a standard.
If you must insist on using terminal, I think the best you can do is to configure your terminal to send `\030@h` for that key. Or in Emacs side, map that key to `event-apply-hyper-modifier` function in the `local-function-key-map`. But even then, it will only work like a chord, rather than a modifier (basically you have to use it like `H b` for it to be interpreted as `H-b`).
alfamadorian · 2022-04-16 08:28
>\\030@h
I'm using Tabby. Can I have Tabby send \\030@h when I press the Hyper key ? Any example of that or how would you do it, using your preferred terminal?;)
nullmove · 2022-04-16 10:36
Sorry I don't even know what Tabby is. All I have ever known in life is urxvt :P and I would configure it by something like this .Xresources:
URxvt.keysym.<key>: string:\030@h
Where the <key> would be something that I pretend is hyper in my normal keyboard, like say Insert or Menu - something that I would never otherwise need.
But as I said, you don't need to do that in Tabby. That escape sequence is emulating pressing `C-x @ h` which Emacs knows to mentally translate as hyper prefix. But you could simply do this in Emacs side:
(let ((insert [(insertchar)]))
(global-unset-key insert)
(define-key local-function-key-map insert 'event-apply-hyper-modifier))
And it should work in the same (underwhelming) way.
alfamadorian · 2022-04-16 11:05
>\\030@h
right, but I want to translate the actual Hyper key to something which can be sent to emacs, cause I want to keep that key.
The Hyper key looks like this in xev:
\`
KeyPress event, serial 34, synthetic NO, window 0x1400001,
root 0x3c6, subw 0x1400002, time 983306878, (39,44), root:(289,363),
state 0x0, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyPress event, serial 34, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306878, (39,44), root:(289,363), state 0x4, keycode 50 (keysym 0xffe1, Shift\_L), same\_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False
KeyPress event, serial 34, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306879, (39,44), root:(289,363), state 0x5, keycode 64 (keysym 0xffe7, Meta\_L), same\_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False
KeyPress event, serial 34, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306879, (39,44), root:(289,363), state 0xd, keycode 133 (keysym 0xffeb, Super\_L), same\_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306956, (39,44), root:(289,363), state 0x4d, keycode 37 (keysym 0xffe3, Control\_L), same\_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306956, (39,44), root:(289,363), state 0x49, keycode 50 (keysym 0xffe1, Shift\_L), same\_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306956, (39,44), root:(289,363), state 0x48, keycode 64 (keysym 0xffe9, Alt\_L), same\_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x1400001, root 0x3c6, subw 0x1400002, time 983306956, (39,44), root:(289,363), state 0x40, keycode 133 (keysym 0xffeb, Super\_L), same\_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False \`
alfamadorian · 2022-04-16 11:18
so, basically, it sends keypress combination of Control\_L, Shift\_L, Meta\_L and Super\_L
nullmove · 2022-04-16 12:08
My mental model is that the Hyper is not a *real* key. Linux kernel code has no implementation for it, it's only a software defined creation by Xorg/X11. Whatever key that's marked as Hyper in your special keyboard, ultimately it's just a key that sends a keycode (probably configurable in firmware?). You have to specifically instruct Xorg to associate that key with hyper (rather than what it's currently guessing based on the layout specified). For example, I have to do this using xmodmap:
clear Mod3
keycode 135 = Hyper_R
add Mod3 = Hyper_R
Whereas 135 is the keycode of whatever I see in `xev` that I want to turn to Hyper. You could try subsituting that to what you see in `xev` for your keyboard. I can't interpret your `xev` dump because there are too many entries, I am not sure which one is supposed to be that.
In any case, whatever `xev` is showing at X11 level is not relevant, if you can even manage to get hyper working at X11 level even that's not relevant, because your terminal emulator ultimately isn't even gonna recognise it, much less pass it on to Emacs. Knowing this state of affairs, Emacs has decided that as workaround it would interpret `C-x @ h` to be Hyper, because people can configure their terminal to send that to Emacs in response to a key it recognises.
So basically, if you really want to use the same "Hyper" key of your keyboard in terminal Emacs, I think you need to first make that key become something recognisable to terminals like Insert (you can do that either at firmware or xmodmap level). And then the above elisp snippet would work.
Or you could stop being insane and ditch the abomination that is terminal emulation ;) GUI Emacs is literally right there, and superior in every conceivable way (except for working in remote machines I will grant, but Tramp exists, even X11 forwarding exists).
ftrx · 2022-04-16 13:15
Beware a thing: various major distros assign super and hyper modifier on Mod4 in xkb (look for X11/xkb/symbols/pc file) and while perfectly doable tweaking xkb is not a nice and easy business especially since it's code is next to being badly documented abandonware with many still using xmodmap...
nanounanue · 2022-04-16 13:47
Hi. Moonlander user here. The "hyper" from moonlander is not the proper hyper key. As you mentioned is a combination of control, alt and another one key (I forgot which one). If you want a proper hyper key `H` you need to setup at software level or you can use the `hyper` key from moonlander if you set all your keybindings to use the `C-M-S-` prefix
I can share you my config later if you like (I choose the `H` method)
ieure · 2022-04-16 14:59
The remappers that work at the hardware level don't help here. Since hyper isn't in the HID, those can't generate a hyper keycode, either, because there isn't one. I don't know if the terminal can recognize a hyper modifier (doubt it, but, you never know), but it's definitely a thing that mainly exists in X11 and Wayland (which inherited xkb from X11) -- so it's something that must be solved at that level.
noman_032018 · 2022-04-16 15:20
It appears that the Moonlander is [supported by qmk](https://github.com/qmk/qmk_firmware/tree/master/keyboards/moonlander), it might be possible to use [some useless key like [F13,F24]](https://usb.org/sites/default/files/hut1_3_0.pdf#chapter.10) as a modifier by having Hyper emit it.
I think that keyboard also lacks a numpad, so all the numpad keycodes are free to reuse.
Now I'm just not sure how one might modify Emacs' expected keycodes for modifiers. Remappers would make that much easier in GUI, but in terminal that might require Emacs-side work. I know there are some chording modes for Emacs, so that could perhaps help in figuring out how to do it.
edit: [Going by this comment](https://old.reddit.com/r/emacs/comments/jxg2t0/want_an_emacsfriendly_keyboard/gcwwg16/), you might have a concrete idea on how to proceed.
edit2: Is it as simple as binding `#'event-apply-hyper-modifier` to the dummy key?
edit3: It isn't. How did you do it? I'm actually quite interested because I'm planning on eventually getting hyper/super pedals (i3wm conflicts with directly using super for Emacs).
ieure · 2022-04-16 18:39
> It appears that the Moonlander is supported by qmk, it might be possible to use some useless key like [F13,F24] as a modifier by having Hyper emit it.
>
QMK is great, and yeah, that's the general approach. I also want to use Hyper on non-programmable (laptop) keyboards, so I have my right and left hyper modifiers bound to print screen and the context menu keys, since one or the other is right of the right alt key on those keyboards. That lets me use the same keymap for internal/external keyboards and have hyper on both. Getting separate X11 keymaps per device is a thing I still haven't gotten to work.
> Now I'm just not sure how one might modify Emacs' expected keycodes for modifiers. Remappers would make that much easier in GUI, but in terminal that might require Emacs-side work. I know there are some chording modes for Emacs, so that could perhaps help in figuring out how to do it.
>
> edit: Going by this comment, you might have a concrete idea on how to proceed.
>
> edit2: Is it as simple as binding #'event-apply-hyper-modifier to the dummy key?
>
> edit3: It isn't. How did you do it? I'm actually quite interested because I'm planning on eventually getting hyper/super pedals (i3wm conflicts with directly using super for Emacs).
>
The solution depends on the OS; what are you using? On Linux, you have to remap at the X level, since those events are what Emacs looks at to determine which modifiers are pressed. On macOS, it happens inside Emacs, since macOS doesn't have any support for extra modifiers. That makes it both a little simpler, but less flexible; you can only repurpose one of the existing modifiers, you can't use an artibrary keycode.
I'm on Linux/X11, since I like EXWM a lot. I have it done via xkb, which is a trementous pain in the ass since its documentation is both incomplete and incomprehensible. You can also use xmodmap, and I have before, but for various reasons I wanted to do it with xkb.
With xkb, you combine "symbols," which are partial keymaps, into a single complete keymap. My symbols for the hyper modifier are:
(this goes into `$HOME/.xkb/symbols/hyper`)
// Hybrid map which works with ThinkPad 6- or 7-row, and Ergodox.
xkb_symbols "hybrid" {
// ThinkPad 7-row.
replace key <MENU> { [ Hyper_L ] };
// ThinkPad 6-row. This key physically exists on the 7-row, too,
// so unfortunately that ends up becoming useless -- but it's a
// reasonable price to pay, I think.
replace key <PRSC> { [ Hyper_R ] };
// Ergodox physically maps the two Hyper keys to the TP 6/7-row
// keys, so no further configuration is necessary.
include "hyper(base)"
};
partial modifier_keys
xkb_symbols "base" {
modifier_map Control { <LCTL> };
modifier_map Mod1 { <LALT>, <RALT> };
modifier_map Mod3 { Hyper_L, Hyper_R };
modifier_map Mod4 { <LWIN>, <RWIN> };
};
The `xkb_symbols` block is a partial keymap. If you want different keys mapped to hyper, you can edit that one, or add a new block based on it -- hopefully it's straightforward to understand.
Then the keymap itself (`$HOME/.xkb/keymap/hybrid`):
xkb_keymap {
xkb_keycodes { include "evdev+aliases(qwerty)" };
xkb_types { include "complete" };
xkb_compat { include "complete" };
xkb_symbols { include "pc+us+inet(evdev)+ctrl(nocaps)+hyper(hybrid)" };
xkb_geometry { include "pc(pc105)" };
};
The important bits there are `xkb_keycodes`, which tell xkb that it's a qwerty keyboard using evdev, and `xkb_symbols`, which pulls in some base keymaps that ship with X11 (`pc`, `us`, `inet(evdev)`, `ctrl(nocaps)`), and the `hybrid` partial map from the `hyper` symbols file.
Then my `$HOME/.xsessionrc` has this in it:
xkbcomp -w0 -I$HOME/.xkb $HOME/.xkb/hybrid $DISPLAY
The annoying thing about this is that when *any* keyboard is hot un/plugged, the keymaps reset to the default, and you have to rerun that command. You can fix this by assigning the keymaps in the Xorg conf based on the USB IDs, but that won't look at the xkb paths in `$HOME`, I hate dumping stuff into random places on the FS, and I've never gotten around to making a package for my keymaps. Some day.
RedditAlready19 · 2022-04-16 19:46
On my stumpwm setup I have Hyper set to caps lock and it actually sends Hyper
alfamadorian · 2022-04-16 20:46
Yes, please share;)
, but how is it not a proper Hyper key? If I look for the definition of the Hyper key, it's not a single key, it's a combination of four modifiers at the same time?
alfamadorian · 2022-04-16 20:47
As you see, I've posted xev output, where it shows key press of the four modifiers, then a release of the four modifiers.
alfamadorian · 2022-04-16 21:53
>Or you could stop being insane and ditch the abomination that is terminal emulation ;)
I fired up GUI Emacs, but it still doesn't see anything when I M-x describe-key.
noman_032018 · 2022-04-16 22:22
Thanks. Unfortunately you seem to be right regarding evdev-level modification/insertion. It seems quite x11/wayland only.
[I think this might be able to emulate the results purely from Emacs](https://github.com/emacsorphanage/key-chord), although that comes at the downside of needing to define a H-<char> chord for every binding you want. That library also wouldn't support something like "C-M-H-S-a" at the moment, while the xkb method would.
nullmove · 2022-04-16 22:42
Well, you still need to do the first part, configure the key to be Hyper at Xorg. Your keyboard claiming to have Hyper is false marketing ;) Hyper doesn't exist at hardware level. As I said, you have to use xmodmap/xkb to instruct Xorg to recognize whatever keycode that key emits as hyper.
ieure · 2022-04-16 22:49
Yeah. I went the xkb route because that did what I needed. I used to use xmodmap, but that was a very long time ago.
Sucks to set up, but it's very nice to have an extra modifier all your own.
nanounanue · 2022-04-17 02:42
Hyper key, in the old keyboards was a single key :)
I was confused also, and have several discussions with the (patient and kind) customer service of moonlander
alfamadorian · 2022-04-18 06:29
ok, I bound a key to F24, to use that for Hyper in Emacs, instead.
Hmm, then I have no reason to call it Hyper, if I just bind to f12 plus a key;)
Can't see it working in console, but I have it working in GUI Emacs for now;)