vscode icon indicating copy to clipboard operation
vscode copied to clipboard

Keyboard mappings with `setxkbmap` on Linux not working

Open tallpants opened this issue 8 years ago • 92 comments

  • VSCode Version: 1.11.0
  • OS Version: Ubuntu 16.04

I have my Caps Lock key bound to Escape using setxkbmap on Linux. This worked fine till 1.10, but broke with 1.11. At first I thought it was an issue with the VSCodeVim extension, but the issue persists with all the other Vim extensions on the marketplace as well. Pressing the escape button still works as expected.

The binding is still respected everywhere else in the operating system, it's only Visual Studio Code that ignores it for some reason.

Steps to Reproduce:

  1. Run setxkbmap -option caps:escape (binds caps to escape for the duration of the session)
  2. Hitting caps lock when in insert mode (with a Vim extension like VSCodeVim installed) no longer puts you normal mode.
  3. Hitting escape still works as expected and puts you in normal mode.

tallpants avatar Apr 06 '17 05:04 tallpants

Same, with swapescape. Oddly caps lock works as escape to cancel in the keybinding editor, and either caps lock or escape cancel the F1 menu. Tried disabling all extensions, wiping user settings and using an empty workspace to no avail.

I have problems with numpad keys too. With num lock off they do nothing, but work as number keys with it on. If I press a direction with numpad off, nothing happens, but then turn it on and type a number and the cursor will move and then put the number.

In the keyboard shortcuts editor numpad PgDn, for example, shows up as numpad3 whether num lock is on or off.

jspaine avatar Apr 06 '17 10:04 jspaine

This is something that might be broken by us dispatching based on scan codes. I am sorry about it, I need some time to investigate how these options should be handled. i.e. should Chromium handle these mappings or should we do it at the application layer.

Workaround to switch VS Code to dispatch based on key code again. Add the following setting: "keyboard.dispatch": "keyCode" and restart VS Code

alexdima avatar Apr 06 '17 21:04 alexdima

Thanks for the workaround! 👍

tallpants avatar Apr 07 '17 01:04 tallpants

The workaround works like a charm, thanks!

graves501 avatar Apr 10 '17 14:04 graves501

I have a similar issue, with my Caps Lock bound to Control, where Code is unable to autoclose the quick open window when pressing Ctrl+Tab and then releasing Control. I've tested the workaround and it does not solve this issue.

Note: this appears to be specifically an issue with detecting the modifier key. Caps+Tab still launches the quick open just fine, and I have other remapped key bindings for arrow key movements that also work fine.

tobico avatar May 08 '17 22:05 tobico

this workaround isn't working for me on vscode 1.12.2-1..

navxio avatar Jun 01 '17 17:06 navxio

@navdeepio Can you please follow our troubleshooting guide at https://github.com/Microsoft/vscode/wiki/Keybindings#troubleshoot

If nothing in there works, then please proceed to create a new issue using the steps in the "I have tried all of the above" section.

alexdima avatar Jun 02 '17 05:06 alexdima

@alexandrudima Do you guys plan on fixing this issue at some point? Or is the workaround satisfactory as a long term solution?

Chillee avatar Jun 21 '17 04:06 Chillee

@Chillee This method needs to be enhanced to account for setxkbmap customizations and then we might need some tweaks here to cover mappings of those scan codes

alexdima avatar Jun 21 '17 07:06 alexdima

Is it tricky or is it feasible as a first time contribution?

Chillee avatar Jun 21 '17 21:06 Chillee

The work would be split between making first a change in native-keymap and then in vscode.

  • the work in native-keymap would involve finding and using X11 specific methods that would capture/return the mappings done via setxkbmap and expose them in some form in the results of _GetKeyMap
  • the work in vscode would involve making changes in macLinuxKeyboardMapper.ts, where the values returned from native-keymap are consumed, and where all keybindings decisions are done for OSX and Linux.

I would be very appreciative if anyone figures out the X11 specific methods / submits a PR for native-keymap. I can tweak or refactor (if the current model is incorrect) in VS Code.

The way we handle keybindings decisions is documented here

alexdima avatar Jun 22 '17 05:06 alexdima

Still experiencing weirdness with 1.21.1 in debian 9.

caps lock and ctrl swapping caused issues. seemed to partially help by swapping settings so that instead of "caps lock and control are swapped", I now have "caps lock is set as another control".

kylebakerio avatar Mar 19 '18 04:03 kylebakerio

Great, now I can use vim mode :)

dagolinuxoid avatar Mar 27 '18 06:03 dagolinuxoid

The workaround unfortunately breaks other things, notable the Ctrl + ` shortcut to toggle the integrated terminal. And yes, I'm using a standard-ish layout (those two keys aren't affected).

jhpratt avatar Apr 10 '18 01:04 jhpratt

@jhpratt, Ctrl + ` works ( at least in my case it toggles the terminal without issues )

dagolinuxoid avatar Apr 12 '18 06:04 dagolinuxoid

Awesome

Loridawn99 avatar Apr 12 '18 06:04 Loridawn99

same problem as @jhpratt, the workaround breaks a lot of shorcuts, (I use an ABNT2 (Brazil) keyboard)

pumpkinlink avatar Jul 20 '18 17:07 pumpkinlink

~the workaround I found was:~

~1. open gnome tweak tool 1.1 disable the caps lock remap (re enabling caps lock default behavior) 2. open vscode 2.1. map "extension.vim_escape" to capslock 3. go back to gnome tweak tool 3.1 map caps lock to esc again~

edit: making the above disabled my actual top left physical Esc key. so I made the follwing instead:

  1. Reset the extension.vim_escape keybinding on the GUI Keyboards Shortcuts screen and remove everything related from keybinding.json
  2. add the following to keybinding.json:
,
    {
        "key": "capslock",
        "command": "extension.vim_escape",
        "when": "editorTextFocus && vim.active && !inDebugRepl"
    },

now both my physical esc key and the xkbmap/gnome-tweak-took remapped caps lock key work as expected. my dconf settings are as follows:

org.gnome.desktop.input-sources.sources: "[('xkb', 'br')]" org.gnome.desktop.input-sources.xkb-options: "['shift:both_capslock', 'caps:escape']"

pumpkinlink avatar Jul 20 '18 17:07 pumpkinlink

@alexandrudima, I just ran into this issue, too. Is there a good reason why vscode uses scan codes? I mean scan codes are not really meant to be used by a user application in Linux. And not using the key codes mapped by xkb, will just lead to a repeatedly running into problems for anyone using a rare keyboard or keyboard layout, or alternate input device pretending to be a keyboard.

Also this won't go away with wayland, as (at last the Wayland implementations I used) still use xkb internally.

rustonaut avatar Aug 06 '18 16:08 rustonaut

We are dispatching by default based on scan codes because those are the only things we receive from Chromium/Electron which we can trust to reflect reality and which have not been processed through magic Chromium mapping tables.

AFAIK, the story goes like this:

  • JS keyboard events get a keyCode field on Windows
  • this makes a lot of sense on Windows, as that is a concept that exists on Windows, and all applications on Windows should dispatch on KeyCodes. Exposing them from a browser to a web application seems natural...
  • the problem is when the same concept is attempted to be supported on OSX and Linux, where there are kb maps but those concepts do not map clearly to the same keyCode concept from Windows.
  • browsers have used creative solutions to come up with keyCode values which appear to make sense on Linux and OSX, but they are inherently broken because the concept of keyCode does not exist natively on those operating systems.
  • we come along and need to render in the UI the key to be pressed to trigger a certain keybinding
  • the creative solutions browsers came up with prevent us from building a reverse map from keyCode to produced character in order to display a good label in the UI.
  • we switch to dispatch on code (scan code) which is a value that does not go through the creative solution and is passed to JS unprocessed. We implement https://github.com/Microsoft/node-native-keymap which uses OS APIs to map scan codes to produced characters. Unfortunately, the code we have on Linux, does not cover the setxkbmap customizations, it appears we need to improve that code...
  • so, in cases where one is using setxkbmap it is probably better to dispatch using the previous keyCode solution, especially when using an English keyboard layout where the creative solution from browsers is reversible and we can print decent labels in the UI. But, when not using setxkbmap and when using a different keyboard layout (like de-DE, etc.) it is preferable to run VS Code with dispatching on code.

Because using setxkbmap is a hint for an advanced user, and using a regular keyboard layout (like de-DE) is not, we have made the decision to dispatch based on scan codes by default to cover most of the folks (including new Linux users). Advanced Linux users (that use setxkbmap) need to go through the hurdle of configuring the dispatch setting...

In the long term, it would be good if we'd improve https://github.com/Microsoft/node-native-keymap to also take into account setxkbmap customizations.

alexdima avatar Aug 07 '18 09:08 alexdima

OMG this is so painful. Tried the keyCode workaround and @pumpkinlink workaround. Nothing works. (I'm using Xubuntu 18.04 btw). Is there a way to map the scan code to <Esc> ?

andyl avatar Aug 07 '18 15:08 andyl

@andyl Configure "keyboard.dispatch": "keyCode". Restart VS Code.

alexdima avatar Aug 08 '18 09:08 alexdima

@alexandrudima thanks for the long explanation.

This is quite a quirky problem, I guess to best (but unlikely to be doable) solution would be to fix how browsers handle keyboard events :sob: .

rustonaut avatar Aug 08 '18 11:08 rustonaut

They are working on it, it just takes time... https://wicg.github.io/keyboard-map/

alexdima avatar Aug 08 '18 13:08 alexdima

@alexandrudima - yeah I tried the "keyboard.dispatch": "keyCode" workaround and it doesn't work on my system. Learning more about the escape key than I ever thought possible. In settings.yml I mapped kj to <Esc> - which does work. But for the real escape key no luck. Interestingly enough: I disabled the setxkbmap modification and it still doesn't work! I also tried to set extension.vim_escape to various Keybindings - no luck. Maybe I am experiencing a voodoo curse or anomalous cosmic rays.

andyl avatar Aug 08 '18 15:08 andyl

The "keyCode" workaround just stopped working for me.

rustonaut avatar Sep 05 '18 15:09 rustonaut

Same here.

efredzb avatar Sep 22 '18 04:09 efredzb

Ubuntu 18.04.1 here: "keyboard.dispatch": "keyCode" still works. (With swapescape)

JoschD avatar Oct 16 '18 14:10 JoschD

Kubuntu 18.04 here: "keyboard.dispatch": "keyCode" doesn't work with capslock rebound to ctrl. VSCode still recognizes capslock, no other electron app / program does.

mlcamilli avatar Oct 23 '18 13:10 mlcamilli

In Ubuntu 18.04, to make Caps Lock become an Escape, apply this patch:

--- a/etc/default/keyboard
+++ b/etc/default/keyboard
@@ -5,6 +5,6 @@
 XKBMODEL="pc105"
 XKBLAYOUT="us"
 XKBVARIANT=""
-XKBOPTIONS=""
+XKBOPTIONS="caps:escape"
 
 BACKSPACE="guess"

restart the computer and add the "keyboard.dispatch": "keyCode" into your vscode settings.

certik avatar Oct 29 '18 15:10 certik