Have a laptop with directional Arrow keys and Fn + Arrows for PageUp/PageDown/Home/End. Want to make those keys such that the Right Control changes them to:
- RCtrl + Up -> Page Up
- RCtrl + Down -> Page Down
- RCtrl + Left -> Ctrl + Page Up
- RCtrl + Right -> Ctrl + Page Down
Left control should continue to work as before.
XKB that is close to working:
The following content is saved to /usr/share/X11/xkb/symbols/custom
and loaded via this command setxkbmap -symbols "pc+us+inet(evdev)+custom"
:
key <UP> {
type= "PC_CONTROL_LEVEL2",
symbols[Group1]= [ Up, NoSymbol ],
actions[Group1] = [NoAction(), RedirectKey(key=<PGUP>, clearMods=Control)] };
key <DOWN> {
type= "PC_CONTROL_LEVEL2",
symbols[Group1]= [ Down, NoSymbol ],
actions[Group1] = [NoAction(), RedirectKey(key=<PGDN>, clearMods=Control)] };
key <LEFT> {
type= "PC_CONTROL_LEVEL2",
symbols[Group1]= [ Left, NoSymbol ],
actions[Group1] = [NoAction(), RedirectKey(key=<PGUP>)] };
key <RGHT> {
type= "PC_CONTROL_LEVEL2",
symbols[Group1]= [ Right, NoSymbol ],
actions[Group1] = [NoAction(), RedirectKey(key=<PGDN>)] };
The Problem:
Unfortunately the script above captures both Control keys, not only the right one. I need the left Control key to not change it's behavior. Changing the PC_CONTROL_LEVEL2 -> PC_RCONTROL_LEVEL2 looks like it should work, but nothing works differently in that case (as if I hadn't made any changes).
Any ideas why PC_RCONTROL_LEVEL2 doesn't do anything?
I have tried bumbling around all sorts of different things, but unfortunately nothing has worked. I can't even seem to keep the right control key from acting as a control key, even after trying to map it directly to another key.
I am currently running Ubuntu 17.10 w/ the default GNOME interface. Thanks!
You need to add a function wrapper as follows.
There are two issues here. I will discuss them first and then give three solutions, all of which work in my tests.
Issue A: The "dangling virtual modifier" bug in xkb configs.
Notice that
type "PC_RCONTROL_LEVEL2"
(defined in/usr/share/X11/xkb/types/pc
) uses the virtual modifierRControl
. For the virtual modifierRControl
to do what we expect, it should be associated with the actual keysymControl_R
via aninterpret
stanza in/usr/share/X11/xkb/compat/pc
. But the virtual modifierRControl
is not associated with any keysym at all, and in fact it is not set up in any way in the compatibility configs:grep RControl /usr/share/X11/xkb/compat/*
returns nothing. This is why you are finding thatPC_RCONTROL_LEVEL2
has no effect, and this can be considered to be a "danglingRControl
config bug" in xkb. (This issue does not affect the typePC_CONTROL_LEVEL2
because that type does not use any virtual modifier - it uses the real modifierControl
.)Issue B: Need a separate real modifier bit for right control, distinct from the
Control
modifier bit.The symbols config file
/usr/share/X11/xkb/symbols/pc
contains:As the left and right control keys are both configured by default to set the
Control
modifier bit, they will behave identically unless explicitly bound to distinct modifier bits via separate modifier maps. Here we of course need the right control key to act as a different modifier than the left control key. This can be done, e.g., by changing the right control key's modifier bit (Control
) to a different available modifier bit, sayMod3
(Mod3
is not bound to any key in the default xkb configs).Here are three ways to address these two issues.
Solution 1: Fix the dangling virtual modifier issue for
RControl
.The workaround below achieves your desired setup (in my tests).
First, include the following in your xkb compatibility configs to interpret the
Control_R
keysym as the virtual modifierRControl
:(E.g., you can save the above to a file, say
rctrlfix
, and then withinxkb_compat { ... }
, change theinclude "complete"
toinclude "complete+rctrlfix"
.)Next, separate the modifier map for the right control key. Since its existing modifier map in the default config uses the keysym
Control_R
, you will need to use the keysymControl_R
when replacing the modifier map; using the key<RCTL>
will not work. You will also need to manually clear and set desired modifier bits in your key emulations. So include the following in your symbols configs:As the modifier map for
Control_R
is being defined a second time, there can be a error message saying that, but it seems harmless.A variant of Solution 1 would be to ditch the keysym
Control_R
altogether, and use a spare keysym in its place that is not a modifier and not used in the compatibility configs (e.g.Pause
), and interpret it as the virtual modifierRControl
in the compatibility configs. That is, replaceControl_R
byPause
throughout in the above configs. This would also avoid the multiple modifier map error message.Alternative workarounds.
Solution 2: Bypass the dangling virtual modifier issue by using a type based on a real modifier (
Mod3
).If the symbols configs are customized as above with
Mod3
being the real modifier bit for the keysymControl_R
(key<RCTL>
), then the same result can be achieved by modifying the types configs (instead of modifying the compatibility configs, which can be left untouched): In the type definition ofPC_RCONTROL_LEVEL2
, replace the virtual modifierRControl
by the real modifierMod3
. (You may want to put this in a new type, and in your key emulations change the type names accordingly.)Solution 3: Re-define
<RCTL>
as the level 3 shifter keysymISO_Level3_Shift
.Still another workaround (without need to touch either the compatibility configs or the types configs) would be to re-define the
<RCTL>
key as the Level3 modifier keysymISO_Level3_Shift
(instead ofControl_R
). Then define your desired key emulations usingtype = "THREE_LEVEL"
and with symbol/action values defined at the third level (instead of the second level). This will work as expected, since (a) the default xkb symbols configs define a "fake" key<LVL3>
as the keysymISO_Level3_Shift
with the real modifier bitMod5
bound to it via a modifier map, (b) the default xkb types configs define the typeTHREE_LEVEL
's level 3 shifting using the virtual modifierLevelThree
, and (c) the default xkb compatibility configs interpret the keysymISO_Level3_Shift
as the virtual modifierLevelThree
, so there is no dangling virtual modifier issue.