Ubuntu – Remap a key to Ctrl and make it behave like Ctrl during text editing

keyboardkeyboard-layoutxkb

I bought a fancy-looking mechanical keyboard in Korea. In general, it works really well except for one thing – even though it has Alt and Ctrl keys on its right side, these keys do not generate the same codes as a "regular" keyboard.

Long story short, Right Alt is the Hangul key (changes between Latin and Korean letters) and Ctrl is Hanja (converts between Hangul and "old" Korean characters). I wanted to use multiple layouts – Korean and my local one (Polish) and keep the best of both worlds – that means making Right Alt emit the keycode for Alt while typing Polish and for Hangul while typing in Korean.

Korean worked out of the box (since the keycodes are correct there), but Polish needed tweaks. I changed the layout (/usr/share/X11/xkb/symbols/pl) by adding the following lines in the active xkb_symbols section:

key <HNGL>  { [ ISO_Level3_Shift ] };
key <HJCV>  { [ Control_R ] };

And I have commented out the lines related to HNGL and HJCV in the "inet" layout, since these were overwriting my changes.

After these changes I got Alt working perfectly, but there was still a problem with Ctrl key not working correctly. In general it works, but when editing text, I should be able to e.g. delete one word by using Ctrl+Backspace combination and I'm unable to do so.

I have executed xset -r 131 in order to disable key repeating for this Ctrl/Hanja key but it still doesn't work like a real Ctrl

Here's the xev output of remapped Hanja:

KeyPress event, serial 34, synthetic NO, window 0x1000001,
root 0x13f, subw 0x0, time 49086462, (88,89), root:(3928,141),
state 0x10, keycode 131 (keysym 0xffe4, Control_R), same_screen YES,
XKeysymToKeycode returns keycode: 105
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False

And here's a regular Ctrl (from other keyboard):

KeyPress event, serial 39, synthetic NO, window 0x1000001,
root 0x13f, subw 0x0, time 49144922, (616,377), root:(4456,429),
state 0x10, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
XLookupString gives 0 bytes: 
XmbLookupString gives 0 bytes: 
XFilterEvent returns: False

Is there anything I can change to make my system treat that key as a full-blown Ctrl?

Best Answer

Assigning a key to another is unique when the key is a modifier. This answer has a good explanation:

The action, when it is a modifier action such as this, changes the current modifier state, which (simply put) is a set of flags recorded in the operating system that record what modifiers are currently "on". [This record] influences what action further keypresses map to.

And so when you are trying to map your key, it is being mapped as a regular key and losing information which specifies how it behaves when multiple keys are pressed.

To demonstrate, run xmodmap. Note that there are two default keys (Control_L and Control_R) mapped to the control modifier. If you run xmodmap -e 'keycode 131 = Control_L' and then xmodmap, the control modifier should still have two keys, so your key isn't being recognized as a modifier.

To map as a modifier:

Clear the modifier key control

xmodmap -e 'clear control'

Add the keycode for the Hanja key

xmodmap -e 'keycode 131 = Control_L'

Lastly, add back the default modifiers:

xmodmap -e 'add control = Control_L'
xmodmap -e 'add control = Control_R'

Now, if you were to run xmodmap again, you will notice a new key has been added for the modifier control, and it should work correctly now.

Here is a link to official Arch Linux instructions on reassigning modifiers to keys on your keyboard.

edit:

for persistent changes, add to /usr/share/X11/xkb/symbols/pl:

key <HJCV> { [ Control_L ] };

modifier_map Control { Control_L, Control_R, <HJCV> };
Related Question