I'm trying to find a fix for a keyboard issue when connecting to a Linux desktop using VMWare Horizon View. The issue seems to be known, and was described in 2012 on VMWare's knowledge base, available on archive.org. I have to add that I don't know much about how XKB works, so digging into this has been a learning experience.
The workarounds listed on the VMWware KB aren't satisfactory. I can confirm the description given, that there's an additional unwanted Control_L
character when I hit AltGr
. When I press AltGr+7 I expect a {
, but instead I get an escape character 0x1b
. This is what it looks like when running xev and hitting AltGr+7 (ISO_Level3_Shift is the expected keypress when hitting AltGr
).
KeyPress event, serial 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444939915, (157,43), root:(388,257),
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 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444939920, (157,43), root:(388,257),
state 0x4, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
XKeysymToKeycode returns keycode: 92
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyPress event, serial 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444944595, (157,43), root:(388,257),
state 0x84, keycode 16 (keysym 0x7b, braceleft), same_screen YES,
XLookupString gives 1 bytes: (1b) "
mbLookupString gives 1 bytes: (1b) "
FilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444944763, (157,43), root:(388,257),
state 0x84, keycode 16 (keysym 0x7b, braceleft), same_screen YES,
XLookupString gives 1 bytes: (1b) "
FilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444951582, (157,43), root:(388,257),
state 0x84, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x3000001,
root 0x521, subw 0x0, time 2444951586, (157,43), root:(388,257),
state 0x80, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
XKeysymToKeycode returns keycode: 92
XLookupString gives 0 bytes:
XFilterEvent returns: False
There's a suggestion on the VMWare KB to press AltGr
, and then press and release the left Ctrl
to trigger a KeyRelease event for Control_L, after which I can press 7
and get the output I'm looking for: XLookupString/XmbLookupString in that case return 7b, which is {
as expected.
So after confirming the problem, I've looked into workarounds in Linux. I ran xkbcomp
to get the live keymap definition by running:
xkbcomp $DISPLAY out.xkb
After looking at the generated out.xkb
, I figured it might be possible to redefine my keymappings to expect Control_L in addition to the other keys. So to select some relevant parts, my out.xkb contained:
xkb_types "complete" {
...
type "FOUR_LEVEL" {
modifiers= Shift+LevelThree;
map[Shift]= Level2;
map[LevelThree]= Level3;
map[Shift+LevelThree]= Level4;
};
};
...
xkb_symbols "pc+no+inet(evdev)" {
...
key <AE07> {
type= "FOUR_LEVEL",
symbols[Group1]= [ 7, slash, braceleft, division ]
};
...
}
The braceleft in the above definition is what I'm trying to get to work right now. My idea was to simply redefine FOUR_LEVEL to expect Control_L in the appropriate cases, like this:
type "FOUR_LEVEL" {
modifiers= Shift+LevelThree+LControl;
map[Shift]= Level2;
map[LevelThree+LControl]= Level3;
map[Shift+LevelThree+LControl]= Level4;
};
I created a mapping with this setup, and then I tried to compile and load my modified file:
xkbcomp ctrl-hack.xkb
xkbcomp ctrl-hack.xkm $DISPLAY
Unfortunately, my changes don't seem to work as I had hoped. I don't get any errors, but I still get the 0x1b
instead of {
character when I hit AltGr+7. What could be going wrong?
Alternatively, I see that some other characters (like €
and $
) seem to work despite also requiring the AltGr
modifier, and receiving an additional unexpected Control_L. But testing while manually pressing Control_L, I see that €
works both with and without Control_L being pressed, so there seems to be some fallback definition for this symbol that isn't explicit in the xkbcomp
output. I haven't figured out how this works yet. Is it possible to define similar fallbacks for the symbols I'm missing? Perhaps some sort of inheritance from console keyboard configuration, for instance? This would probably come from the same place as the 0x1b
character that I receive when pressing Ctrl-AltGr-7. I can't find it in the XKB-config, so it has to be defined somewhere else.