#456 closed defect (fixed)
swap command and control key for mac osx clients
Reported by: | alas | Owned by: | alas |
---|---|---|---|
Priority: | minor | Milestone: | 0.11 |
Component: | client | Version: | |
Keywords: | osx keyboard | Cc: |
Description (last modified by )
When using osx one expects command-c to copy, for instance... but the osx client xpra sessions dont' recognize command-c - rather recognizing ctrl-c as a windows client would expect.
Ideally, the ctrl functionality can be mapped to command for the osx client.
(Oddly, it seems that the xpra interprets the command key as a non-sticky NumLock
key.)
I'm attaching a (hopefully) illustrative file of the behavior with the gtk_view_keyboard tool.
Attachments (10)
Change History (24)
Changed 7 years ago by
Attachment: | xpra_keyboard_output_control-v-command added |
---|
comment:1 Changed 7 years ago by
Description: | modified (diff) |
---|---|
Keywords: | keyboard added; command v ctrl removed |
Milestone: | → 0.11 |
Owner: | changed from Antoine Martin to Antoine Martin |
Status: | new → assigned |
Summary: | osx client treats ctrl key as osx would generally treat the command key → swap command and control key for mac osx clients |
Updating bug title: the client does exactly what is expected (bar NumLock
issues) but we need to swap the two keys around to make *nix applications do what mac users expect in terms of key mapping.
comment:2 Changed 7 years ago by
Please post *raw* keyboard data, without xpra interfering.
Looks like some modifier is mis-mapped and causing NumLock
to fire.
Changed 7 years ago by
Attachment: | osx-local-ctrl-v-cmd-key-mappings.txt added |
---|
osx local key mappings of ctrl and command
comment:3 Changed 7 years ago by
Attached *raw* keyboard data as requested. osx 10.9, using Xpra.app/Contents/Helpers/Keyboard_Tool.
Included ctrl, ctrl-c, ctrl-v, command, cmd-c, cmd-v ... with both mac and microsoft keyboards.
Let me know if I overlooked anything.
Changed 7 years ago by
Attachment: | osx-swapkeys+numlock.patch added |
---|
swap control and meta keys and also deal with numlock as per #453
comment:4 Changed 7 years ago by
The patch osx-swapkeys+numlock.patch fixes both this bug and #453 for me.
Please confirm so I can apply and backport to v0.10.x
Changed 7 years ago by
Attachment: | osx-swapkeys+numlock-v2.patch added |
---|
swap control and meta keys and also deal with numlock as per #453 (also emulate numlock state)
comment:5 Changed 7 years ago by
Applied in r4747, this works for me and allows me to toggle numlock on and off.
Note:
- numlock always starts "ON" since that is what most mac keyboards seem to do, and we do not detect the actual state (not sure how we could - looks very hard to do) - if the user has numlock off when starting the xpra session, then the numlock state will continue to be the opposite of what the user expects (the opposite of what may be shown by the little green light)
- the swapping of "control" and "meta" may not be suitable for the v0.10.x branch, which is a bug-fix only branch after all
FYI: to apply the patches posted in tickets, you usually do:
cd xpra/trunk/src patch -p0 < /path/to/osx-swapkeys+numlock-v2.patch
comment:6 Changed 7 years ago by
Added keyboard debug in r4749, use it with:
XPRA_KEYBOARD_DEBUG=1 xpra attach ...
comment:7 Changed 7 years ago by
Owner: | changed from Antoine Martin to alas |
---|---|
Status: | assigned → new |
If meta/control swapping does not work for you (worked OK for me when I tested with xterm
and gedit
: control-C to stop terminal commands and usual cut&paste shortcuts) then please post the output of the client running with the debug option from comment:6
Note: with r4751 you can toggle the swapping of keys at runtime. (adding a command line switch was a bit harder so I didn't bother)
Changed 7 years ago by
Attachment: | xpra-cmd-test1 added |
---|
xpra 0.11r4759 osx 10.9 keyboard_debug output
Changed 7 years ago by
Attachment: | xpra-cmd-test2 added |
---|
xpra 0.11r4759 osx 10.9 keyboard_debug output (from gedit)
Changed 7 years ago by
Attachment: | xpra-cmd-local-test3.txt added |
---|
another local Keyboard_Tool test, for very direct comparison (same keys as gedit)
comment:8 Changed 7 years ago by
Attached files of output with keyboard_debug=1... xpra 0.11r4759, osx 10.9 ...
xpra-cmd-test1:
Started with xterms, started google-chrome, clicked youtube link, started video & first tried cmd-c then cmd-v to copy/paste some text... then tried the same with ctrl-c then ctrl-v. cmd-v output a 'v'. ctrl-v output nothing.
xpra-cmd-test2:
Started with xterms, started gedit, typed in text (I am a happy camper). Highlit & cmd-c ‘happy’… replaced text with ‘c’. Tried cmd-v, output ‘v’. Highlit & ctrl-c ‘camper’ … nothing happened. Tried ctrl-v… opened ‘View’ drop-menu.
xpra-cmd-local-test3:
Just for the sake of thoroughness. Same keyboard as test1 and 2, same keystrokes as gedit test (test2).
comment:9 Changed 7 years ago by
Owner: | changed from alas to Antoine Martin |
---|---|
Status: | new → assigned |
It just occurred to me that the mac keyboards also swap the *location* of command and "option", see:
So maybe virtualbox does this translation for me already... Did you try hitting the "option" key instead during testing?
(we just ignore "mod2" which is numlock)
Anyway, those logs are fairly long, here's what I am really interested in:
- when typing control-C only (from xpra-cmd-test2), I see:
mask_to_names(<flags 0 of type GdkModifierType>)=['mod2'] process_key_event swapping Control_L for Meta_L send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '', 'keyname': 'Meta_L', 'pressed': True, 'keyval': 65507, 'keycode': 59}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1', 'mod2'] send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod1', 'mod2'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': True, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1', 'mod2'] send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod1', 'mod2'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': False, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1', 'mod2'] process_key_event swapping Control_L for Meta_L send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod1', 'mod2'], 'group': 0, 'string': '', 'keyname': 'Meta_L', 'pressed': False, 'keyval': 65507, 'keycode': 59}>)
- doing the same thing on my vbox machine:
mask_to_names(<flags 0 of type GdkModifierType>)=[] process_key_event swapping Control_L for Meta_L send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': [], 'group': 0, 'string': '', 'keyname': 'Meta_L', 'pressed': True, 'keyval': 65507, 'keycode': 59}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1'] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['mod1'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': True, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1'] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['mod1'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': False, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_CONTROL_MASK of type GdkModifierType>)=['mod1'] process_key_event swapping Control_L for Meta_L send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['mod1'], 'group': 0, 'string': '', 'keyname': 'Meta_L', 'pressed': False, 'keyval': 65507, 'keycode': 59}>)
Is identical, bar the"numlock"="mod2"
which is unset in my case. So swapping "Control
" for "Meta
" works exactly the same. We don't change the actual keycode just the keyname and the list of modifiers from then on, but that doesn't seem to be necessary (though I will try to handle that in a future patch).
- when typing command-C only (from xpra-cmd-test2), I see:
mask_to_names(<flags 0 of type GdkModifierType>)=['mod2'] process_key_event swapping Meta_L for Control_L send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '', 'keyname': 'Control_L', 'pressed': True, 'keyval': 65511, 'keycode': 55}>) mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>)=['mod2'] send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': True, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>)=['mod2'] send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': 'c', 'keyname': 'c', 'pressed': False, 'keyval': 99, 'keycode': 8}>) mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD2_MASK | GDK_META_MASK of type GdkModifierType>)=['mod2'] process_key_event swapping Meta_L for Control_L send_key_action(3, <GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '', 'keyname': 'Control_L', 'pressed': False, 'keyval': 65511, 'keycode': 55}>)
- doing the same thing on my vbox machine:
mask_to_names(<flags 0 of type GdkModifierType>)=[] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': [], 'group': 1, 'string': '', 'keyname': 'Alt_L', 'pressed': True, 'keyval': 65513, 'keycode': 58}>) mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>)=['control'] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['control'], 'group': 1, 'string': '\xc3\xa7', 'keyname': 'ccedilla', 'pressed': True, 'keyval': 231, 'keycode': 8}>) mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>)=['control'] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['control'], 'group': 1, 'string': '\xc3\xa7', 'keyname': 'ccedilla', 'pressed': False, 'keyval': 231, 'keycode': 8}>) mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>) meta_modifier=mod1, control_modifier=control mask_to_names(<flags GDK_MOD1_MASK of type GdkModifierType>)=['control'] send_key_action(1, <GTKKeyEvent object, contents: {'modifiers': ['control'], 'group': 0, 'string': '', 'keyname': 'Alt_L', 'pressed': False, 'keyval': 65513, 'keycode': 58}>) mask_to_names(<flags 0 of type GdkModifierType>) meta_modifier=mod1, control_modifier=control
And here we see that the key that I press comes up as "MOD1
" whereas the real key for "command" seems to be "META
"...
So, as I understand it:
VirtualBox
swaps the "Left Windows-Start-Menu
" key (aka "option
" key in osx) with the "Alt_L
" key (aka "command
" key in osx)VirtualBox
intercepts the "Left Windows-Start-Menu
" key so I cannot use it to trigger "META
"
Fortunately, it doesn't do anything to the "Right Windows-Start-Menu
" key and that one does come up as "META
" in the VM.
Which means that I still need to:
- change the code to handle "
META
" - handle both left and right keys, so maybe patch the mask before it gets translated into names
- translate keycodes (and keyval?) too so this will be more correct and future proof
comment:10 Changed 7 years ago by
Owner: | changed from Antoine Martin to alas |
---|---|
Status: | assigned → new |
("META
" is "command
")
- r4760 adds a
FIXME
not explaining why this ends up being harder to implement than it should be - r4761 properly detects the
META
key seen on OSX, and swaps it for "control
" - r4762 ensures that we not only send the proper list of modifiers with key presses but that the actual keypresses (of either
control
ormeta
) end up with valid translated keysyms and keycodes (if at all possible) - r4763 adds some debug logging when swapping modifiers
Works for me, but as I said in comment:9 I cannot press the left command
key through virtualbox... only the right one!
So, please re-test, you should see this in the log:
- the key translation map (near the beginning):
set_modifier_mappings(..) key translations={'Meta_R': (59, 'Control_L'), 'Control_L': (55, 'Alt_L'), 'Meta_L': (59, 'Control_L'), 'Control_R': (54, 'Alt_R')}
- when pressing control:
swap keys: translating key \ '<GTKKeyEvent object, contents: {'modifiers': ['mod1', 'mod2'], 'group': 0, 'string': '', 'keyname': 'Control_L', 'pressed': False, 'keyval': 65507, 'keycode': 59}>' \ to (55, 'Alt_L')
- when pressing meta (
Meta_R
in my case):swap keys: translating key \ '<GTKKeyEvent object, contents: {'modifiers': ['mod2'], 'group': 0, 'string': '', 'keyname': 'Meta_R', 'pressed': True, 'keyval': 65512, 'keycode': 54}>' \ to (59, 'Control_L')
- when pressing other keys, buttons or simply moving the mouse around with "control" held (*):
mask_to_names swapping control for meta: control for mod1
- when pressing other keys, buttons or simply moving the mouse around with "meta" (aka "command") held (*):
mask_to_names swapping meta for control: mod1 for control
- toggling the swap keys option in the menu should revert to "normal" behaviour (the one that confuses apple users)
(*) Note: some modifier keys will not show when moving the mouse around, that is the case for me with the "right windows start menu
" key under virtualbox. I'm not sure if this is because of virtualbox, osx or gtk... Doesn't seem to cause any problems though.
Changed 7 years ago by
Attachment: | osx-ctrl-v-cmd-finaltest2.txt added |
---|
osx ctrl v cmd test confirmation of key swappings
comment:11 Changed 7 years ago by
Testing confirms that the swapping is behaving as you'd hoped. (I clicked both the right and left command keys, resulting in 'Meta_R', 'pressed': True in the one case and :False in the other.
Attached the output in case you'd like to look at more debugging output.
comment:12 Changed 7 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
Good, closing at last.
This will not be backported to v0.10.x as this is too intrusive.
comment:13 Changed 7 years ago by
Fix menu entry to say Command
and not Option
in r6434. Will backport.
comment:14 Changed 5 weeks ago by
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/456
osx xpra command v. ctrl key output