Context:
When the numerical keypad is activated (num lock on) and I press the '.' key then it is printed ';' in the xpra client.
Here are some logs:
setxkbmap -print
:
xkb_keymap { xkb_keycodes { include "xfree86+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr+inet(pc105)" }; xkb_geometry { include "pc(pc105)" }; };
setxkbmap -query
:
rules: base model: pc105 layout: fr
xmodmap -pm
:
xmodmap: up to 7 keys per modifier, (keycodes in parentheses): shift Shift_L (0x32), Shift_R (0x3e), Shift_L (0x8e) lock Caps_Lock (0x42) control Control_L (0x25), Control_R (0x6d), Control_L (0x8f) mod1 Alt_L (0x40), Alt_L (0x79), Meta_R (0x7a), Alt_L (0x7d), Alt_L (0x91), Alt_R (0x92), Meta_L (0x9c) mod2 Num_Lock (0x4d) mod3 Super_L (0x73), Super_R (0x74), Super_L (0x7f) mod4 Hyper_L (0x80), Hyper_R (0x94) mod5 Mode_switch (0x8), ISO_Level3_Shift (0x71), ISO_Level3_Shift (0x7c)
xmodmap -pke
: xmodmap-pke.txt
xpra info | grep keyboard
: xpra-info-keyboard.txt
Keymap_info.exe
output: win32-keymap-info.txt
windows computer (I pressed the '.' key only once): screenshot.jpg
time).
KeyPress event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278199, (94,80), root:(98,103), state 0x0, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278199, (94,80), root:(98,103), state 0x10, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278200, (94,80), root:(98,103), state 0x10, keycode 59 (keysym 0x3b, semicolon), same_screen YES, XLookupString gives 1 bytes: (3b) ";" XmbLookupString gives 1 bytes: (3b) ";" XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278201, (94,80), root:(98,103), state 0x10, keycode 59 (keysym 0x3b, semicolon), same_screen YES, XLookupString gives 1 bytes: (3b) ";" XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278201, (94,80), root:(98,103), state 0x10, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278201, (94,80), root:(98,103), state 0x10, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0xe00001, root 0x44, subw 0x0, time 402278280, (94,80), root:(98,103), state 0x0, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False
xmodmap -pke output (copy to attachment to make the ticket more readable)
Keymap_info.exe output (copy to attachment to make the ticket more readable)
"xpra info | grep keyboard" output (copy to attachment to make the ticket more readable)
(edit: replacing large data with attachments)
Well, I've tried to reproduce this by plugging an external keyboard and using USB pass-through with virtualbox then setting mswindows to 'FR' layout, and I just cannot see any of this crazy behaviour where one keypress ends up generating almost a dozen key events. I always get exactly two events (key down, key up).
Are you using vmware or something else that could interfere with the keyboard?
It definitely looks like something is messing up with Num_Lock
and we get two key-up events for a single key-down... which is very odd.
Confirmed: I think it is safe to ignore the repeated keys and Num_Lock
weirdness which are more than likely caused by a virtual machine (KVM) accessed over RDP. Not a problem with GTK or the OS reporting the wrong keys multiple times.
Summary of the attachments above (parts relating to the key we are interested in) and more:
91
0xffae
KP_Decimal
XKeysymToKeycode
: 129
XLookupString
: "."
Num_Lock
off, we get the same keycode and keysym, the difference is:
KP_Delete
xmodmap -pke
has it mapped as:
keycode 91 = KP_Delete KP_Decimal KP_Delete KP_Decimal KP_Delete KP_Decimal KP_Delete KP_Decimal
Note that we also have:
keycode 134 = KP_Decimal KP_Decimal KP_Decimal KP_Decimal KP_Decimal KP_Decimal KP_Decimal KP_Decimal
This is broadly similar to what is found on a plain Linux host (bar 8 entries created instead of just 4.. caused by Xkb vs core api)
xpra info | grep keyboard
output, we see KP_Decimal
mapped as:
keyboard.keycode.KP_Delete=91 keyboard.keycode.KP_Decimal=134 keyboard.keysym.Delete=107 keyboard.keysym.Delete.46=107 keyboard.keysym.KP_Decimal=134
So the automatic key mapping has chosen the second option for KP_Decimal
.
46 period 110 0 0 46 period 110 0 1 46 period 190 0 1
Two keycodes... and quite different values from the ones we find for Delete
:
65535 Delete 46 0 0 65535 Delete 46 0 1 65535 Delete 46 1 0 65535 Delete 46 1 1
The keycode for Delete
is the keyval
for KP_Decimal
!?
-d keyboard
:
parse_key_event(<gtk.gdk.Event at 01E9AFC8: GDK_KEY_PRESS keyval=period>, True)=\ <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '.', \ 'keyname': 'period', 'pressed': True, 'keyval': 46, 'keycode': 110}> handle_key_action(ClientWindow(1), <GTKKeyEvent object, contents: \ {'modifiers': ['mod2'], 'group': 0, 'string': '.', \ 'keyname': 'period', 'pressed': True, 'keyval': 46, 'keycode': 110}>) wid=1 send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '.', \ 'keyname': 'period', 'pressed': True, 'keyval': 46, 'keycode': 110}>) mask_to_names(<flags 0 of type GdkModifierType>) GetKeyState(VK_NUMLOCK)=1, names=['mod2'] parse_key_event(<gtk.gdk.Event at 01E9AFE0: GDK_KEY_RELEASE keyval=period>, False)=\ <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '.', \ 'keyname': 'period', 'pressed': False, 'keyval': 46, 'keycode': 110}> handle_key_action(ClientWindow(1), <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '.', \ 'keyname': 'period', 'pressed': False, 'keyval': 46, 'keycode': 110}>) wid=1 send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string':'.', \ 'keyname': 'period', 'pressed': False, 'keyval': 46, 'keycode': 110}>
TIL: the event contains: 'string': '.', 'keyname': 'period', 'pressed': True, 'keyval': 46, 'keycode': 110
-d keyboard
:
get_keycode(110, period, ('mod2',)) is_native_keymap=False, found using translation: 59 handle_key(1,True,period,46,59,('mod2',)) keyboard_sync=True is_modifier(59) not found handle keycode pressing 59: key period fake_key(59, True) scheduling key repeat timer with delay 750 for period / 59 get_keycode(110, period, ('mod2',)) is_native_keymap=False, found using translation: 59 handle_key(1,False,period,46,59,('mod2',)) keyboard_sync=True is_modifier(59) not found handle keycode unpressing 59: key period fake_key(59, False) cancelling key repeat timer: 10964 for period / 59
TIL: we translate (110, period)
to (59, period)
.
ugly patch which renames the windows keyboard keyname for the "."
The patch above seems to work for me. Before merging, I would like to find a cleaner way of patching the gtk keymap in the per-platform classes rather than having it completely hardcoded. Then I'll worry about backports.
Does the beta win32 build work for you? (no need to update the server)
For reference, here's the server keymapping phase (edited log summary):
setxkbmap -layout fr
using gtk keycodes: [..., [46, 'KP_Decimal', 110, 0, 0], [46, 'KP_Decimal', 110, 0, 1], ...
keycodes={..., 110: set([('KP_Decimal', 0), ('KP_Decimal', 1)]), ...}
preserved mappings:
... 60 = ['colon', 'slash', 'colon', 'slash', 'periodcentered', 'division', 'periodcentered'] ... 91 = ['KP_Delete', 'KP_Decimal', 'KP_Delete', 'KP_Decimal'] ...
translate_keycodes(8, 255, {... 110: set([('KP_Decimal', 0), ('KP_Decimal', 1)]), ... 91: set([('KP_Delete', 2), ('KP_Decimal', 1), ('KP_Decimal', 3), ('KP_Delete', 0)]), ... 129: set([('KP_Decimal', 0), ('KP_Decimal', 2), ('KP_Decimal', 1), ('KP_Decimal', 3)]), ...}
assign(110, set([('KP_Decimal', 0), ('KP_Decimal', 1)])) preserve matches for set([('KP_Decimal', 0)]) : { 129: set([('KP_Decimal', 0), ('KP_Decimal', 2), ('KP_Decimal', 1), ('KP_Decimal', 3)]), \ 91: set([('KP_Delete', 2), ('KP_Decimal', 1), ('KP_Decimal', 3), ('KP_Delete', 0)])} found direct preserve superset for 110 : set([('KP_Decimal', 0)]) -> 129 : set([('KP_Decimal', 0), ('KP_Decimal', 2), ('KP_Decimal', 1), ('KP_Decimal', 3)]) set_keycodes key 110 (set([('KP_Decimal', 0), ('KP_Decimal', 2), ('KP_Decimal', 1), ('KP_Decimal', 3)])) mapped to keycode=129
set_keycodes key -1 (set([('KP_Delete', 2), ('KP_Decimal', 1), ('KP_Decimal', 3), ('KP_Delete', 0)])) mapped to keycode=91
translated keycodes={..., (110, 'KP_Decimal'): 129, 'KP_Decimal': 91, ... }
['KP_Delete', 'KP_Decimal', 'KP_Delete', 'KP_Decimal', '', '', ''] -> [65439L, 65454L, 65439L, 65454L, None, None, None] ['KP_Decimal', 'KP_Decimal', 'KP_Decimal', 'KP_Decimal', '', '', ''] -> [65454L, 65454L, 65454L, 65454L, None, None, None]
r6667 is a better fix, but too intrusive to backport.
So I've applied the more ugly workaround in r6669 for the v0.13.x branch, this will be part of 0.13.4
Some related tickets I've found:
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/588