On Fri, Nov 17, 2017 at 1:42 PM, <jm+guacamole@roth.lu> wrote:


I was not referring to any particular issue I am having. I simply wanted to understand the different layers that make things what they are.

This is what I found out. Hope it helps someone in the future. Feel free to correct it, or include parts of it in the docs otherwise ;-)

The different layers:
* Local keybaord layout (hardware)
* Local keyboard layout (OS)
* Guacamole session keyboard layout
* Remote keyboard layout (OS)
* obviosuly, remote hardware keyboard layout does not matter in this case

In other terms:
* Local keyboard layout (OS)         <-- determines symbol you want to see appear on destination
* Guacamole session keyboard layout  <-- the keyboard layout on which the POSITION of that symbol is determined
* Remote keyboard layout (OS)        <-- the keyboard layout on which the key at that position is pressed

This means:
* Local keyboard layout (hardware) should match local keyboard layout (OS).
* Guacamole session keyboard layout should match remote configured keyboard layout (OS).
* For everything to work 100%, all of these should be the same, otherwise there might be symbols that you can't type since either your local keyboard (hardware) or the remote keyboard layout (OS) doesn't have a key at that position, or the local symbol does not exist on the the remote keyboard layout at all.

Almost, but not quite. ;)

Guacamole itself is independent of keyboard layout. Its protocol and API are designed this way. The only exception to this at the moment is RDP, because RDP depends on scancodes for key events. This means that strictly in the case of RDP, you have the following:

* Local keyboard layout (browser-side)
* RDP session keyboard layout
* Remote keyboard layout (within the RDP session)

That middle part is a translation layer which functions to produce a series of RDP scancodes given a Guacamole key event. If you type "@", for example, Guacamole will need to send a different series of scancodes to the RDP server if the RDP server uses a US English keyboard layout (Shift+2) or a German keyboard (AltGr+Q). Since different layouts have different modifiers with different semantics, the translation layer must also take into account modifier state, possibly pressing/releasing yet more keys to obtain the proper modifier state remotely and then restore the original state once the key event has finished.

Again, for example, take an "@" key event. If the local side uses a US keyboard, then Shift will be pressed down at the time the "@" key event is received remotely. If the remote side uses a German layout (and the connection is properly configured), then Guacamole's RDP support knows to:

1) Release Shift (must not be pressed to properly type "@")
2) Press AltGr
3) Press Q
4) Release AltGr
5) Press Shift (restoring modifier state)

For all other supported protocols (VNC, SSH, telnet), scancodes are never involved, and no such complicated translation layer is necessary.

In the case of the workarounds you mentioned in your earlier email, both are valid workarounds and both deal with different aspects of RDP and the translation layer. When Guacamole encounters a key event which cannot be translated for RDP (because the layout declared for the remote side in the connection configuration does not have such a key), it leverages Unicode events. Unicode events allow the character to be typed, but are not actually key events as far as Windows applications are concerned, so they are only used as a fallback. This is why setting the remote keyboard layout to any keyboard layout supported by Guacamole (and setting the same layout on the connection) should allow you to type normally regardless of local layout. It is a design principle of Guacamole that the local user should not need to worry about remote config, including keyboard layout.

The other workaround, which involved setting keyboard layouts incorrectly, relies on the way RDP deals with scancodes. By misinforming Guacamole about the remote keyboard layout, and setting the local keyboard layout to match, the various local keys will map to remote keys perfectly on a 1-to-1 basis, thus the keyboard should behave as expected. This goes against the design principle I mentioned earlier, however, so I really wouldn't recommend this unless you have no choice. Its only advantage would be proper behavior of dead keys, which are a known issue: https://issues.apache.org/jira/browse/GUACAMOLE-352

- Mike