xpra icon
Bug tracker and wiki

#1665 closed defect (fixed)

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

Reported by: Alex Owned by: Antoine Martin
Priority: critical Milestone: 2.2
Component: keyboard Version: trunk
Keywords: keyboard kb mapping german AltGr Cc: t.mainka@…

Description (last modified by Antoine Martin)

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-r15692 (xpra-2.1-0.20170421r15692.el7_3.x86_64)
  • same with: xpra v2.1.2-r16903 (xpra-2.1.2-1.r16903.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.

Attachments (6)

Keyboard_info.exe.txt (243 bytes) - added by Alex 12 months ago.
keyboard info on client
Keymap_info.exe.txt (72.1 KB) - added by Alex 12 months ago.
keymap info on client
System.txt (9.3 KB) - added by Alex 12 months ago.
system info client
Server_Info.txt (110.8 KB) - added by Alex 12 months ago.
system info server
xpra_cmd.log (601.9 KB) - added by Alex 12 months ago.
"xpra_cmd.exe […] --debug=keyboard" stderr on client
de.png (45.9 KB) - added by Antoine Martin 11 months ago.
standard? german keyboard layout

Download all attachments as: .zip

Change History (14)

Changed 12 months ago by Alex

Attachment: Keyboard_info.exe.txt added

keyboard info on client

Changed 12 months ago by Alex

Attachment: Keymap_info.exe.txt added

keymap info on client

Changed 12 months ago by Alex

Attachment: System.txt added

system info client

Changed 12 months ago by Alex

Attachment: Server_Info.txt added

system info server

comment:1 Changed 12 months ago by Antoine Martin

Status: newassigned

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

Changed 12 months ago by Alex

Attachment: xpra_cmd.log added

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

comment:2 in reply to:  1 Changed 12 months ago by Alex

Replying to 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!)

comment:3 Changed 11 months ago by Antoine Martin

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

Changed 11 months ago by Antoine Martin

Attachment: de.png added

standard? german keyboard layout

comment:4 Changed 11 months ago by Antoine Martin

Description: modified (diff)
Priority: majorcritical

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:
standard? german keyboard layout

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
Last edited 11 months ago by Antoine Martin (previous) (diff)

comment:5 Changed 11 months ago by Antoine Martin

Owner: changed from Antoine Martin to Alex
Status: assignednew

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?

comment:6 Changed 10 months ago by Antoine Martin

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 wiki/Keyboard and #1380.

Last edited 10 months ago by Antoine Martin (previous) (diff)

comment:7 Changed 10 months ago by Antoine Martin

Owner: changed from Alex to Antoine Martin
Status: newassigned

r17573 has caused a regression with my UK layout.

comment:8 Changed 10 months ago by Antoine Martin

Resolution: fixed
Status: assignedclosed

Fixed in r17666, backport in r17667.

Note: See TracTickets for help on using tickets.