Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard mapping: German keyboard special characters wrong (client: Win7, server:CentOS7) #1665

Closed
totaam opened this issue Oct 17, 2017 · 23 comments

Comments

@totaam
Copy link
Collaborator

totaam commented Oct 17, 2017

Issue migrated from trac ticket # 1665

component: keyboard | priority: critical | resolution: fixed | keywords: keyboard kb mapping german AltGr

2017-10-17 17:12:43: aberg created the issue


Unfortunately the keyboard mapping doesn't work well for a german
keyboard (CentOS 7 <-> CentOS 7 works well).
I've tried and can confirm his observation using different 2.x.x Clients on Win 7.
Switching the keyboard (in xpra-context-menu) from "auto" to "de" makes no difference.

Example:
The pipe symbol | is AltGR + < on a german keyboard.
In an xpra session you only get <.
Same for @ (AltGr + q) and others.

Server:

  • CentOS 7.4.1708
  • xpra v2.1-15692 (xpra-2.1-0.20170421r15692.el7_3.x86_64)
  • same with: xpra v2.1.2-16903 (xpra-2.1.2-1.16903.el7_4.x86_64)
    Client:
  • Win 7 x86_64
  • xpra v2.1.2-r16904
  • Xpra_cmd.exe start ssh:%CENTOS7-SERVER% --start-child="xterm -ls" --debug=keyboard

xev output for local input on server:

    KeyPress event, serial 30, synthetic NO, window 0x4400001,
        root 0x28e, subw 0x0, time 535304170, (389,-605), root:(889,416),
        state 0x10, 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 33, synthetic NO, window 0x4400001,
        root 0x28e, subw 0x0, time 535304218, (389,-605), root:(889,416),
        state 0x90, keycode 52 (keysym 0xbb, guillemotright), same_screen YES,
        XLookupString gives 2 bytes: (c2 bb) "»"
        XmbLookupString gives 2 bytes: (c2 bb) "»"
        XFilterEvent returns: False
    
    KeyRelease event, serial 33, synthetic NO, window 0x4400001,
        root 0x28e, subw 0x0, time 535304307, (389,-605), root:(889,416),
        state 0x90, keycode 52 (keysym 0xbb, guillemotright), same_screen YES,
        XLookupString gives 2 bytes: (c2 bb) "»"
        XFilterEvent returns: False
    
    KeyRelease event, serial 33, synthetic NO, window 0x4400001,
        root 0x28e, subw 0x0, time 535304530, (389,-605), root:(889,416),
        state 0x90, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
        XKeysymToKeycode returns keycode: 92
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

xev output in xpra session:

    KeyPress event, serial 33, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295354, (568,425), root:(697,581),
        state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295384, (568,425), root:(697,581),
        state 0x6014, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295384, (568,425), root:(697,581),
        state 0x6010, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295384, (568,425), root:(697,581),
        state 0x6010, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295384, (568,425), root:(697,581),
        state 0x6000, keycode 113 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295547, (568,425), root:(697,581),
        state 0x80, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295547, (568,425), root:(697,581),
        state 0x90, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295547, (568,425), root:(697,581),
        state 0x90, keycode 183 (keysym 0x3c, less), same_screen YES,
        XKeysymToKeycode returns keycode: 94
        XLookupString gives 1 bytes: (3c) "<"
        XmbLookupString gives 1 bytes: (3c) "<"
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295629, (568,425), root:(697,581),
        state 0x90, keycode 183 (keysym 0x3c, less), same_screen YES,
        XKeysymToKeycode returns keycode: 94
        XLookupString gives 1 bytes: (3c) "<"
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295901, (568,425), root:(697,581),
        state 0x6090, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536295901, (568,425), root:(697,581),
        state 0x6090, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536297311, (568,425), root:(697,581),
        state 0x6080, keycode 113 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyPress event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536297312, (568,425), root:(697,581),
        state 0x6000, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False

    KeyRelease event, serial 36, synthetic NO, window 0xa00001,
        root 0x25d, subw 0x0, time 536297312, (568,425), root:(697,581),
        state 0x6010, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

Local xkbmap on server is:

    xkb_keymap {
            xkb_keycodes  { include "evdev+aliases(qwertz)" };
            xkb_types     { include "complete"      };
            xkb_compat    { include "complete"      };
            xkb_symbols   { include "pc+de+inet(evdev)"     };
            xkb_geometry  { include "pc(pc105)"     };
    };
    rules:      evdev
    model:      pc105
    layout:     de

Xpra session xkbmap is:

    xkb_keymap {
    };
    rules:      base
    layout:    de

Logs will be attached.

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:14:45: aberg uploaded file Keyboard_info.exe.txt (0.2 KiB)

keyboard info on client

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:15:17: aberg uploaded file Keymap_info.exe.txt (72.1 KiB)

keymap info on client

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:19:24: aberg uploaded file System.txt (9.3 KiB)

system info client

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:25:16: aberg uploaded file Server_Info.txt (110.8 KiB)

system info server

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:28:47: antoine changed status from new to assigned

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:28:47: antoine commented


Thanks for the details.

I assume that the keyboard looks like the one in the picture here: [https://en.wikipedia.org/wiki/German_keyboard_layout].

We have had problems with AltGr in the past: #62, #602.
Hopefully this is not related to this bug: #1578, or even this one: #1607 as this would require a more fundamental change: #1049.

I'll take a look when I get a chance. This may not make the cut for 2.2

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:33:08: aberg uploaded file xpra_cmd.log (601.9 KiB)

"xpra_cmd.exe [...] --debug=keyboard" stderr on client

@totaam
Copy link
Collaborator Author

totaam commented Oct 17, 2017

2017-10-17 17:45:41: aberg commented


Replying to [comment:1 Antoine Martin]:

I assume that the keyboard looks like the one in the picture here: [https://en.wikipedia.org/wiki/German_keyboard_layout].
It looks pretty much like that. (At least the pipe and @-sign are in place.)

We have had problems with AltGr in the past: #62, #602.
Now i get where the Level3_shift is coming from ))

Hopefully this is not related to this bug: #1578, or even this one: #1607 as this would require a more fundamental change: #1049.

My understanding of X11-keymap-handling is poor, so please just tell me if you need more info or so.

I'll take a look when I get a chance. This may not make the cut for 2.2
Thanks!)

@totaam
Copy link
Collaborator Author

totaam commented Dec 4, 2017

2017-12-04 09:07:59: antoine commented


Some related changes in r17553, r17554, r17555 (debug logging, etc)

Actual fixes in r17556 (see #1380), r17557. Tested with win7 client, Fedora 27 server.

We still have two problems to fix here:

  • r17558: win32 clients give us duplicate mappings for some keys, we now try harder to accommodate this, but we should send valid keymaps instead
  • r17559: specifying --keyboard-layout=de defines xkbmap attributes and makes us switch to a "native keymap" mode, which breaks things

@totaam
Copy link
Collaborator Author

totaam commented Dec 5, 2017

2017-12-05 17:45:39: antoine uploaded file de.png (45.9 KiB)

standard? german keyboard layout
de.png

@totaam
Copy link
Collaborator Author

totaam commented Dec 5, 2017

2017-12-05 18:21:23: antoine changed priority from major to critical

@totaam
Copy link
Collaborator Author

totaam commented Dec 5, 2017

2017-12-05 18:21:23: antoine edited the issue description

@totaam
Copy link
Collaborator Author

totaam commented Dec 5, 2017

2017-12-05 18:21:23: antoine commented


r17569 fixes the issue when overriding keyboard options on non-X11 clients: the options are sent separately, so the server no longer switches to "native" mode when it shouldn't.


The other issue turns out to be much more tricky: the reason why this sort of works is because for non-X11 clients we use a flat keymap, without using level or group. We map the keys we get from the client using the formulae:

index = group*2+level

This works reasonably well in most cases - that is for keyboards without too many levels and groups.
But with the german layout, the default X11 keymap we get with setxkbmap de looks like this (using our keymap tool to dump it):

keyval          name                        keycode group   level
51              3                           12      0       0
167             section                     12      0       1
179             threesuperior               12      0       2
163             sterling                    12      0       3

All very straightforward and I believe that this matches the standard layout:
[[Image(de.png)]]

But the one we get from MS Windows using the same API, looks like this (ouch):

keyval          name                        keycode group   level
51              3                           51      0       0
163             sterling                    51      0       1
51              3                           51      1       0
167             section                     51      1       1
179             threesuperior               51      1       2
34              quotedbl                    51      2       0
51              3                           51      2       1
35              numbersign                  51      2       2

That's 3 groups, with up to 3 levels in groups 1 and 2.
No idea how users access the extra groups and levels.
And we end up mapping it like this, which isn't quite right:

51              3                           12      0       0
163             sterling                    12      0       1
179             threesuperior               12      0       2
51              3                           12      0       3

And I don't see a way to generate the correct index values from the MS Windows keymap.

This is where it gets more complicated.
Here's what we get when we press the keys client side on win32 (ignoring the workarounds we need for properly detecting AltGr..):

  • "3"
parse_key_event(<gtk.gdk.Event at 000000003129e9e0: GDK_KEY_PRESS keyval=3>, True)=<GTKKeyEvent object, contents: \
    {'modifiers': [], 'group': 1, 'string': '3', 'keyname': '3', 'pressed': True, 'keyval': 51, 'keycode': 51}>
  • Shift + "3"
parse_key_event(<gtk.gdk.Event at 000000003129e990: GDK_KEY_PRESS keyval=section>, True)=<GTKKeyEvent object, contents: \
    {'modifiers': ['shift'], 'group': 1, 'string': '\xa7', 'keyname': 'section', 'pressed': True, 'keyval': 167, 'keycode': 51}>
  • AltGr + "3":
parse_key_event(<gtk.gdk.Event at 000000003129ed28: GDK_KEY_PRESS keyval=threesuperior>, True)=<GTKKeyEvent object, contents: \
    {'modifiers': ['mod5'], 'group': 1, 'string': '\xb3', 'keyname': 'threesuperior', 'pressed': True, 'keyval': 179, 'keycode': 51}>
  • AltGt + Shift + "3"
parse_key_event(<gtk.gdk.Event at 000000003129ec38: GDK_KEY_PRESS keyval=threesuperior>, True)=<GTKKeyEvent object, contents: \
    {'modifiers': ['shift', 'mod5'], 'group': 1, 'string': '\xb3', 'keyname': 'threesuperior', 'pressed': True, 'keyval': 179, 'keycode': 51}>

This last one differs from the X11 keymap, which gives "sterling" instead.

I believe that what we should be doing is to leave the server-side "de" keymap as it is after we call setxkbmap de (I am oversimplifying here), then:

  • add extra modifiers (Alt_R can go MIA, etc)
  • add missing keysyms to unbound keycodes
  • generate the translation table so that keycodes map to the server keycode (and ignore the keyname? ignore the string?) - that way, as long as the modifiers are set correctly, we should get the right key
  • continue to ignore the group attribute, level should be managed by Shift / CapsLock

@totaam
Copy link
Collaborator Author

totaam commented Dec 6, 2017

2017-12-06 12:11:33: antoine changed status from assigned to new

@totaam
Copy link
Collaborator Author

totaam commented Dec 6, 2017

2017-12-06 12:11:33: antoine changed owner from antoine to Alex

@totaam
Copy link
Collaborator Author

totaam commented Dec 6, 2017

2017-12-06 12:11:33: antoine commented


More fixes - this ticket keeps on giving!

  • r17572: with non native X11 keymaps, keep the full server keymap and translate all keys, map any missing modifiers if needed
  • r17573 let the client specify if using layout groups is going to work (and adjust ms windows client's values)
  • r17574 fix keysym / keycode matching (try to match the group / level)
  • r17575 better keysym debug logging, ie: XPRA_DEBUG_KEYSYMS="dead_circumflex,Shift_L" xpra start
  • r17576 skip group=0 for MS Windows client keymaps (never helpful?)

With these changes, we keep the keymap intact and the client can trigger the right keys.
These changes should be backwards compatible, and some may be backported (r17574 at least)

This should do, may follow up in #1716.

@alex: does that work for you?

@totaam
Copy link
Collaborator Author

totaam commented Dec 10, 2017

2017-12-10 08:04:04: antoine commented


r17591 reverts the win32 group changes (this only affected the python2 builds, which explains why this went unnoticed): non zero groups are only defined for non-us layouts, causing this regression with us layouts:
client failed to provide any keycodes

This may reduce improvements to the keymap compatibility code when connecting to older server versions.

See also Keyboard and #1380.

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 08:50:50: antoine changed status from new to assigned

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 08:50:50: antoine changed owner from Alex to antoine

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 08:50:50: antoine commented


r17573 has caused a regression with my UK layout.

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 11:13:45: antoine changed status from assigned to closed

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 11:13:45: antoine set resolution to fixed

@totaam
Copy link
Collaborator Author

totaam commented Dec 16, 2017

2017-12-16 11:13:45: antoine commented


Fixed in r17666, backport in 17667.

@totaam totaam closed this as completed Dec 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant