xpra icon
Bug tracker and wiki

Opened 8 days ago

Last modified 6 days ago

#2769 new defect

XPRA inside Docker HTML5 Client German Keyboard wrong Keys

Reported by: Günter Owned by: Günter
Priority: major Milestone: 4.1
Component: keyboard Version: 4.0.x
Keywords: keyboard, german, docker, html5 Cc:

Description (last modified by Antoine Martin)

Hi XPRA Developers!

I am running XPRA-server with html turned on inside a Debian buster based docker container.
Currently we are connecting to xpra using the html5 client from Linux, mac-OS and windows computers.
Depending on the client computer and browser, different problems with keys arise, but i will stick to windows 10 for now.

user@16383962afbb:~$ xpra --version
xpra v4.0.1-r26379

Setting Keyboard to Germany in connect.html:
"ALT GR" + "ß" should give "\" but outputs "ß"

2020-05-19 08:15:50,203 client   2 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= ControlLeft keycode= 17
2020-05-19 08:15:50,203 client   2 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-19 08:15:50,204 client   2 keyboard passing clipboard modifier key event to browser: Control_L
2020-05-19 08:15:50,204 client   2 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= AltRight keycode= 18
2020-05-19 08:15:50,549 client   2 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Minus keycode= 219
2020-05-19 08:15:50,549 client   2 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-19 08:15:50,638 client   2 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Minus keycode= 219
2020-05-19 08:15:50,711 client   2 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= ControlLeft keycode= 17
2020-05-19 08:15:50,712 client   2 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-19 08:15:50,712 client   2 keyboard passing clipboard modifier key event to browser: Control_L
2020-05-19 08:15:50,712 client   2 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= AltRight keycode= 18

When using the English keyboard "ALT GR" + "ß" works as expected, but then of course the other specials keys like ä, ö, ü are not working anymore.

Setting Keyboard to English USA in connect.html: ALT GR + ß should give \ and actually outputs \.

2020-05-19 08:37:41,983 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= ControlLeft keycode= 17
2020-05-19 08:37:41,983 client   3 keyboard _get_keyboard_layout() keyboard_layout= us
2020-05-19 08:37:41,984 client   3 keyboard passing clipboard modifier key event to browser: Control_L
2020-05-19 08:37:41,984 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= AltRight keycode= 18
2020-05-19 08:37:42,244 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Minus keycode= 219
2020-05-19 08:37:42,244 client   3 keyboard _get_keyboard_layout() keyboard_layout= us
2020-05-19 08:37:42,315 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Minus keycode= 219
2020-05-19 08:37:42,474 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= ControlLeft keycode= 17
2020-05-19 08:37:42,474 client   3 keyboard _get_keyboard_layout() keyboard_layout= us
2020-05-19 08:37:42,474 client   3 keyboard passing clipboard modifier key event to browser: Control_L
2020-05-19 08:37:42,474 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= AltRight keycode= 18

It is always the same outcome using XPRA Version 3 or 4 or the latest beta.

--no-keyboard-sync makes no difference

user@16383962afbb:~$ setxkbmap -print
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(pc104)"	};
};
user@16383962afbb:~$ setxkbmap -query
rules:      evdev
model:      evdev
layout:     de
user@16383962afbb:~$ xmodmap -pke
bash: xmodmap: command not found

xmodmap -pke and xmodmap -pm commands not found inside container
xkbprint -label name $DISPLAY does nothing

I am not sure whether this is a problem within xpra or my dockerfile.

If there is anything else I can provide, please let me know. Thank you for all your effort you put into this project!

Best Regards,
Günter

Attachments (6)

Dockerfile (1.5 KB) - added by Günter 8 days ago.
Dokerfile
xpra_info.txt (197.6 KB) - added by Günter 8 days ago.
xpra info
keyboard (152 bytes) - added by Günter 8 days ago.
keyboard docker file
locale (75 bytes) - added by Günter 8 days ago.
locale docker file
KB_Germany.png (27.7 KB) - added by Antoine Martin 8 days ago.
German keyboard layout
xkb-keysyms.patch (6.5 KB) - added by Antoine Martin 7 days ago.
work in progress patch

Download all attachments as: .zip

Change History (16)

Changed 8 days ago by Günter

Attachment: Dockerfile added

Dokerfile

Changed 8 days ago by Günter

Attachment: xpra_info.txt added

xpra info

Changed 8 days ago by Günter

Attachment: keyboard added

keyboard docker file

Changed 8 days ago by Günter

Attachment: locale added

locale docker file

comment:1 Changed 8 days ago by Antoine Martin

Description: modified (diff)
Milestone: 4.1
Status: newassigned

Changed 8 days ago by Antoine Martin

Attachment: KB_Germany.png added

German keyboard layout

comment:2 Changed 8 days ago by Antoine Martin

I'm going to assume that this is the keyboard layout you are referring to:
German keyboard layout

And that the problematic keys are all in the cluster to the right and below 0.

comment:3 Changed 7 days ago by Antoine Martin

With keyboard debugging enabled at both ends and setting up my local X11 keyboard using setxkbmap de:

2020-05-20 10:23:09,464 client   8 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= AltRight keycode= 225
2020-05-20 10:23:09,468 client   8 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 10:23:09,472 will try levels: [2, 6, 3, 7, 0, 4, 1, 5]
2020-05-20 10:23:09,473 do_get_keycode(225, 'ISO_Level3_Shift', 1, ['mod2', 'mod5'], 0)=92 (level=2, shift=False, mode=1, keysyms=['ISO_Level3_Shift', '', 'ISO_Level3_Shift'])
2020-05-20 10:23:09,473 process_key_action([b'key-action', 1, b'ISO_Level3_Shift', 1, [b'mod2', b'mod5'], 225, b'altgraph', 225, 0]) server keycode=92, group=0
2020-05-20 10:23:09,473 set_keyboard_layout_group(0) ignored, no layout groups support
2020-05-20 10:23:09,473 set_keyboard_layout_group(0) ignored, value unchanged
2020-05-20 10:23:09,474 filtered_modifiers_set([])=set()
2020-05-20 10:23:09,474 modifier 'mod5' ignored (in ignored keynames=['ISO_Level3_Shift', 'Mode_switch'])
2020-05-20 10:23:09,474 filtered_modifiers_set(['mod2', 'mod5'])={'mod2'}
2020-05-20 10:23:09,475 make_keymask_match(['mod2', 'mod5']) current mask: set(), wanted: {'mod2'}, ignoring=92/['ISO_Level3_Shift'], keys_pressed={37: 'Control_L'}
2020-05-20 10:23:09,475 change_mask(set(), False, remove) failed=[]
2020-05-20 10:23:09,475 keynames(mod2)=['Num_Lock'], keycodes=[77], nuisance=True, nuisance keys={'lock', 'mod2'}
2020-05-20 10:23:09,476 change_mask(add) ['mod2', 'mod5'] modifier 'mod2' using keycode 77
2020-05-20 10:23:09,476 change_mask({'mod2'}, True, add) failed=[]
2020-05-20 10:23:09,477 handle_key((1, 1, 'ISO_Level3_Shift', 225, 92, ['mod2', 'mod5'], True, True))
2020-05-20 10:23:09,477 handle keycode pressing    92: key 'ISO_Level3_Shift'
2020-05-20 10:23:09,477 fake_key(92, True)
2020-05-20 10:23:09,644 client   8 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Minus keycode= 189
2020-05-20 10:23:09,644 client   8 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 10:23:09,647 will try levels: [2, 6, 3, 7, 0, 4, 1, 5]
2020-05-20 10:23:09,647 do_get_keycode(189, 'backslash', 1, ['mod2', 'mod5'], 0)=20 (level=4, shift=False, mode=1, keysyms=['ssharp', 'question', 'ssharp', 'question', 'backslash', 'questiondown', 'U1E9E'])
2020-05-20 10:23:09,647 removing 'mod5' from modifiers
2020-05-20 10:23:09,647 switching group from 0 to 1
2020-05-20 10:23:09,647 process_key_action([b'key-action', 1, b'backslash', 1, [b'mod2', b'mod5'], 189, b'\\', 189, 0]) server keycode=20, group=1
2020-05-20 10:23:09,647 set_keyboard_layout_group(1) ignored, no layout groups support
2020-05-20 10:23:09,647 set_keyboard_layout_group(0) ignored, value unchanged
2020-05-20 10:23:09,647 filtered_modifiers_set(['mod2', 'mod5'])={'mod2', 'mod5'}
2020-05-20 10:23:09,647 filtered_modifiers_set(['mod2'])={'mod2'}
2020-05-20 10:23:09,647 make_keymask_match(['mod2']) current mask: {'mod2', 'mod5'}, wanted: {'mod2'}, ignoring=20/['backslash'], keys_pressed={37: 'Control_L'}
2020-05-20 10:23:09,647 keynames(mod5)=['ISO_Level3_Shift', 'Mode_switch'], keycodes=[92, 108, 203], nuisance=False, nuisance keys={'lock', 'mod2'}
2020-05-20 10:23:09,648 change_mask(remove) ['mod2'] modifier 'mod5' using keycode 92
2020-05-20 10:23:09,648 change_mask({'mod5'}, False, remove) failed=[]
2020-05-20 10:23:09,648 change_mask(set(), True, add) failed=[]
2020-05-20 10:23:09,648 is_modifier(20) not found
2020-05-20 10:23:09,648 handle_key((1, 1, 'backslash', 189, 20, ['mod2'], False, True))
2020-05-20 10:23:09,648 handle keycode pressing    20: key 'backslash'
2020-05-20 10:23:09,648 fake_key(20, True)
2020-05-20 10:23:09,838 client   8 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Minus keycode= 189
2020-05-20 10:23:09,841 client   8 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 10:23:09,846 process_key_action([b'key-action', 1, b'backslash', 0, [b'mod2', b'mod5'], 189, b'\\', 189, 0]) server keycode=20, group=1
2020-05-20 10:23:09,846 set_keyboard_layout_group(1) ignored, no layout groups support
2020-05-20 10:23:09,846 set_keyboard_layout_group(0) ignored, value unchanged
2020-05-20 10:23:09,847 filtered_modifiers_set(['mod2'])={'mod2'}
2020-05-20 10:23:09,847 filtered_modifiers_set(['mod2', 'mod5'])={'mod2', 'mod5'}
2020-05-20 10:23:09,848 make_keymask_match(['mod2', 'mod5']) current mask: {'mod2'}, wanted: {'mod2', 'mod5'}, ignoring=20/['backslash'], keys_pressed={37: 'Control_L'}
2020-05-20 10:23:09,848 change_mask(set(), False, remove) failed=[]
2020-05-20 10:23:09,848 keynames(mod5)=['ISO_Level3_Shift', 'Mode_switch'], keycodes=[92, 108, 203], nuisance=False, nuisance keys={'lock', 'mod2'}
2020-05-20 10:23:09,849 change_mask(add) ['mod2', 'mod5'] modifier 'mod5' using keycode 92
2020-05-20 10:23:09,849 change_mask({'mod5'}, True, add) failed=[]
2020-05-20 10:23:09,850 is_modifier(20) not found
2020-05-20 10:23:09,850 handle_key((1, 0, 'backslash', 189, 20, ['mod2', 'mod5'], False, True))
2020-05-20 10:23:09,850 handle keycode unpressing  20: key 'backslash'
2020-05-20 10:23:09,850 fake_key(20, False)
2020-05-20 10:23:09,901 client   8 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= AltRight keycode= 225
2020-05-20 10:23:09,902 process_key_action([b'key-action', 1, b'ISO_Level3_Shift', 0, [b'mod2'], 225, b'altgraph', 225, 0]) server keycode=92, group=0
2020-05-20 10:23:09,902 set_keyboard_layout_group(0) ignored, no layout groups support
2020-05-20 10:23:09,902 set_keyboard_layout_group(0) ignored, value unchanged
2020-05-20 10:23:09,903 modifier 'mod5' ignored (in ignored keynames=['ISO_Level3_Shift', 'Mode_switch'])
2020-05-20 10:23:09,903 filtered_modifiers_set(['mod2', 'mod5'])={'mod2'}
2020-05-20 10:23:09,903 filtered_modifiers_set(['mod2'])={'mod2'}
2020-05-20 10:23:09,903 handle_key((1, 0, 'ISO_Level3_Shift', 225, 92, ['mod2'], True, True))
2020-05-20 10:23:09,903 handle keycode unpressing  92: key 'ISO_Level3_Shift'
2020-05-20 10:23:09,903 fake_key(92, False)
2020-05-20 10:23:11,384 filtered_modifiers_set(['mod2'])={'mod2'}
2020-05-20 10:23:11,385 filtered_modifiers_set([])=set()
2020-05-20 10:23:11,386 make_keymask_match([]) current mask: {'mod2'}, wanted: set(), ignoring=None/None, keys_pressed={37: 'Control_L'}
2020-05-20 10:23:11,387 keynames(mod2)=['Num_Lock'], keycodes=[77], nuisance=True, nuisance keys={'lock', 'mod2'}
2020-05-20 10:23:11,388 change_mask(remove) [] modifier 'mod2' using keycode 77
2020-05-20 10:23:11,389 change_mask({'mod2'}, False, remove) failed=[]
2020-05-20 10:23:11,389 change_mask(set(), True, add) failed=[]

Which can be summarized as:

  • client sees AltRight key
  • server presses ISO_Level3_Shift
  • client sees Minus key
  • server tries to locate the matching keycode for backslash, using:
    • will try levels: [2, 6, 3, 7, 0, 4, 1, 5]
    • do_get_keycode(189, 'backslash', 1, ['mod2', 'mod5'], 0)=20 (level=4, shift=False, mode=1, keysyms=['ssharp', 'question', 'ssharp', 'question', 'backslash', 'questiondown', 'U1E9E'])
    • removing 'mod5' from modifiers
    • switching group from 0 to 1

So it doesn't find a backslash at level 2 (AltGr aka ISO_Level3_Shift) and ends up switching group to match it.

That's because the de keymap uses more than 1 level.. and the X11 core keyboard API doesn't tell us that.
I think the only viable fix is to use xkb for looking up keysyms, PITA.

Changed 7 days ago by Antoine Martin

Attachment: xkb-keysyms.patch added

work in progress patch

comment:4 Changed 7 days ago by Antoine Martin

Owner: changed from Antoine Martin to Günter
Status: assignednew

This should be fixed in r26421 by using the Xkb code for looking up the keysyms.
We now use the more correct keysym lookup:

will try levels: [2, 6, 3, 7, 0, 4, 1, 5]
do_get_keycode(219, 'backslash', 1, ['mod2', 'mod5'], 0)=20 (level=2, shift=False, mode=1, keysyms=['ssharp', 'question', 'backslash', 'questiondown', 'U1E9E'])

And we correctly match with level=2.


I have backported this change in r26422.
It is enabled by default in the v4.0.x branch, but needs to be enabled manually with the v3.0.x branch:

XPRA_XKB=1 xpra start ...

This may change in the future if there are no regressions.
(this type of change is known to cause problems - see #2648)


@guenter: does that work for you?

comment:5 Changed 7 days ago by Günter

Thank you, Antoine! I wanted to try it, but I end up with Version xpra v4.0.1-r26379
When I browse through the repositories both stable and beta I can't find r26421 and r26422. I am looking inside here https://xpra.org/dists/buster/main/binary-amd64/
Am I doing something wrong? I deleted all my docker build caches, containers and images, just to be sure that I don't get any cached stuff.
If backported means -sorry, I am not very familiar with software development - that those changes where patched from those future versions into 26379, than my answer, that it still behaves the same.

Your assumption about the keyboard layout was correct.

Not sure, whether this is relevant now, but here are a few more tests:

LINUX:

Firefox/Chromium:
öäü,ß working
@ (AltGr+q) working
tic/backtic (dead keys): not working, both output space
^ (dead key) not working, outputs space
\ (Altgr+ß) not working, outputs ß
| (Altgr+<) working

MAC:

Google Chrome:
öäü,ß working
@ (Option+L) not working, outputs nothing
tic/backtic (dead keys): not working, outputs space
^ (dead key) not working, outputs space
\ (Option+Shift+7) not working, outputs nothing
| (Option+7) not working, outputs nothing

Firefox:
öäü,ß working
@ (Option+L) not working, outputs nothing
tic (dead key): not working, outputs ^
backtic (dead key): not working, outputs ^
^ (dead key) not working, outputs space
\ (Option+Shift+7) not working, outputs nothing
| (Option+7) not working, outputs nothing

WINDOWS:

Google Chrome:
öüäß working
@ (AltGr+q) working
tic/backtic (dead keys): not working, both output '
^ (dead key) working
\ (Altgr+ß) not working, outputs ß
| (Altgr+<) working

Firefox:
öüäß working
@ (AltGr+q) working
tic/backtic (dead keys): not working, both output ^
^ (dead key) working
\ (Altgr+ß) not working, outputs ß
| (Altgr+<) working

comment:6 Changed 7 days ago by Antoine Martin

When I browse through the repositories both stable and beta I can't find r26421 and r26422.

Until new beta builds become available, your only option is to apply the patch by hand. Something like this:

cd /usr/lib/..something../*packages/xpra
patch -p4 < ~/Downloads/changeset_26422.patch

comment:7 Changed 7 days ago by Günter

Hi, I just wanted to report back, that I was able to apply the patch and test from a Windows 10 Client. Now everything works except for tic/backtic.

´ (` then Space) outputs ' 
2020-05-20 18:48:48,547 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-20 18:48:48,548 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:48:48,616 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-20 18:48:49,059 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Space keycode= 32
2020-05-20 18:48:49,059 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:48:49,110 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Space keycode= 32

` (Shift + ´ then Space) outputs ' 
2020-05-20 18:54:26,663 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= ShiftLeft keycode= 16
2020-05-20 18:54:26,663 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:54:27,097 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-20 18:54:27,097 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:54:27,166 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-20 18:54:27,466 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= ShiftLeft keycode= 16
2020-05-20 18:54:27,467 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:54:28,209 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Space keycode= 32
2020-05-20 18:54:28,209 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-20 18:54:28,291 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Space keycode= 32


From MAC and Linux nothing has changed, it is still like described in comment 5. Hopefully tomorrow I can provide keyboard debug logs for those systems, if that would be helpful.
Thank you for the patch you already provided!

comment:8 Changed 6 days ago by Antoine Martin

There are actually two more problems:

Tick key event:

KeyboardEvent {isTrusted: true, key: "Dead", code: "Equal", location: 0, ctrlKey: false, …}
 altKey: false
 bubbles: true
 cancelBubble: false
 cancelable: true
 charCode: 0
 code: "Equal"
 composed: true
 ctrlKey: false
 currentTarget: null
 defaultPrevented: true
 detail: 0
 eventPhase: 0
 isComposing: false
 isTrusted: true
 key: "Dead"
 keyCode: 187
 location: 0
 metaKey: false
 path: (6) [textarea#pasteboard, div, body, html, document, Window]
 repeat: false
 returnValue: false
 shiftKey: false
 sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
 srcElement: textarea#pasteboardtarget: textarea#pasteboard
 timeStamp: 581895.015
 type: "keyup"
 view: Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
 which: 187
 __proto__: KeyboardEvent ) key= Equal keycode= 187

(Backtick is the same, just with shiftKey: true)

And comparing it to the "real" = (omitting attributes that are identical):

KeyboardEvent {isTrusted: true, key: "=", code: "Digit0", location: 0, ctrlKey: false, …}
 code: "Digit0"
 key: "="
 keyCode: 48
 timeStamp: 1285706.0150000015
 which: 48
 __proto__: KeyboardEvent ) key= Digit0 keycode= 48

So, I don't see any way of safely mapping Equal to tick or backtick.

Another problem is that the first event we get is a "keyup" (the "keydown" event is missing altogether), the next one generates both a "keydown" and "keyup"... What a mess.


So the solutions adopted in r26426:

  • map the keycode (and hope this doesn't cause regressions with other keyboard layouts - this lookup table should probably be per-layout...)
  • simulate keypress events when they're missing

Then r26427 adds the keycodes used on mswindows...

Hopefully, none of these changes cause regression with #2547 (see r25034) or other key layouts.

I have not tested on macos at all.


@guenter: you can apply those two patches to your html5 client. (usually in /usr/share/xpra/www)

comment:9 Changed 6 days ago by Antoine Martin

Support for macos should be fixed in r26428. (briefly tested)

comment:10 Changed 6 days ago by Günter

Thank you for the patches, I applied all three of them.
Now for Windows and Linux everything works except for the forward tic.
On MacOS forward tic and tilde are not working.

Windows:

´ (´ + Space) outputs '

2020-05-21 21:11:15,692 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-21 21:11:15,692 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-21 21:11:15,765 client   3 keyboard last keycode pressed= 221 , keycode= 221 , pressed= false , str= Dead
2020-05-21 21:11:15,765 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Equal keycode= 221
2020-05-21 21:11:16,002 client   3 keyboard last keycode pressed= 0 , keycode= 32 , pressed= true , str= ´
2020-05-21 21:11:16,003 client   3 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Space keycode= 32
2020-05-21 21:11:16,003 client   3 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-21 21:11:16,062 client   3 keyboard last keycode pressed= 32 , keycode= 32 , pressed= false , str=  
2020-05-21 21:11:16,062 client   3 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Space keycode= 32

Linux (running virtualized connected through RDP):

´ (´ + Space) outputs '
2020-05-21 21:14:57,032 client   5 keyboard oninput: '´'
2020-05-21 21:14:57,032 client   5 keyboard key-action,1,acute,true,,180,´,180,0
2020-05-21 21:14:57,032 client   5 keyboard key-action,1,acute,false,,180,´,180,0
2020-05-21 21:14:57,089 client   5 keyboard last keycode pressed= 0 , keycode= 187 , pressed= false , str= Dead
2020-05-21 21:14:57,091 client   5 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Equal keycode= 187
2020-05-21 21:14:57,091 client   5 keyboard _get_keyboard_layout() keyboard_layout= de
2020-05-21 21:14:57,162 client   5 keyboard last keycode pressed= 187 , keycode= 32 , pressed= true , str=  
2020-05-21 21:14:57,163 client   5 keyboard processKeyEvent( true ,  [object KeyboardEvent] ) key= Space keycode= 32
2020-05-21 21:14:57,213 client   5 keyboard last keycode pressed= 32 , keycode= 32 , pressed= false , str=  
2020-05-21 21:14:57,213 client   5 keyboard processKeyEvent( false ,  [object KeyboardEvent] ) key= Space keycode= 32
2020-05-21 21:14:57,213 client   5 keyboard _get_keyboard_layout() keyboard_layout= de

Pressing the tic key twice on windows and three times on mac and linux outputs the tic.

For MacOS it needed a small change to r26428, so that the left Option Key also works:

if (str=="AltGraph" || (keyname=="Alt_R" && (Utilities.isWindows() || Utilities.isMacOS())) || (keyname=="Alt_L" && Utilities.isMacOS())) {
this.altgr_state = pressed;
keyname = "ISO_Level3_Shift";
str = "AltGraph";
}

On MacOS the Tilde is not working:
MAC: ~ (Option+N) outputs ~n

Note: See TracTickets for help on using tickets.