Fn有一台带有方向箭头键和+ 箭头(表示PageUp/ PageDown/ Home/ )的笔记本电脑End。想要将这些键设置为右控制键将它们更改为:
- RCtrl+ Up->Page Up
- RCtrl+ Down->Page Down
- RCtrl+ Left-> Ctrl+Page Up
- RCtrl+ Right-> Ctrl+Page Down
左控制键应继续像以前一样工作。
即将开始工作的 XKB:
/usr/share/X11/xkb/symbols/custom
以下内容通过此命令保存并加载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>)] };
问题:
不幸的是,上面的脚本捕获了两个 Control 键,而不仅仅是右键。我需要左键Control才能不改变它的行为。更改PC_CONTROL_LEVEL2->PC_RCONTROL_LEVEL2看起来它应该可以工作,但是在这种情况下没有任何变化(好像我没有做任何改变)。
知道为什么 PC_RCONTROL_LEVEL2 不执行任何操作吗?
我尝试了各种不同的方法,但不幸的是,什么都没用。我甚至无法阻止右控制键充当控制键,即使尝试将其直接映射到另一个键。
我目前正在运行带有默认 GNOME 界面的 Ubuntu 17.10。谢谢!
答案1
这里有两个问题。我将首先讨论它们,然后提供三种解决方案,这些解决方案均在我的测试中有效。
问题 A: xkb 配置中的“悬垂虚拟修饰符”错误。
请注意,type "PC_RCONTROL_LEVEL2"
(在 中定义/usr/share/X11/xkb/types/pc
)使用了虚拟修饰符RControl
。为了使虚拟修饰符
RControl
达到我们期望的效果,它应该Control_R
通过
interpret
中的节与实际的键符相关联/usr/share/X11/xkb/compat/pc
。但是虚拟修饰符RControl
根本不与任何键符相关联,事实上它没有以任何方式在兼容性配置中设置:
grep RControl /usr/share/X11/xkb/compat/*
不返回任何内容。这就是为什么您发现PC_RCONTROL_LEVEL2
没有效果的原因,这可以被视为RControl
xkb 中的“悬空配置错误”。(此问题不会影响类型,PC_CONTROL_LEVEL2
因为该类型不使用任何虚拟修饰符 - 它使用真实修饰符Control
。)
问题 B: 需要一个单独的实修饰位来进行右控制,与修饰位不同Control
。
符号配置文件/usr/share/X11/xkb/symbols/pc
包含:
modifier_map Control { Control_L, Control_R };
由于左控制键和右控制键都默认配置为设置修饰符Control
位,因此除非通过单独的修饰符映射明确绑定到不同的修饰符位,否则它们的行为将完全相同。在这里,我们当然需要右控制键充当与左控制键不同的修饰符。例如,可以通过将右控制键的修饰符位 ( Control
) 更改为不同的可用修饰符位来实现,例如Mod3
(Mod3
在默认 xkb 配置中未绑定到任何键)。
以下是解决这两个问题的三种方法。
解决方案 1:修复悬垂虚拟修饰符问题RControl
。
下面的解决方法实现了您想要的设置(在我的测试中)。
首先,在您的 xkb 兼容性配置中包含以下内容,以将Control_R
键符解释为虚拟修饰符
RControl
:
partial default xkb_compatibility "rctrlinterpret" {
virtual_modifiers RControl;
interpret Control_R+Any {
virtualModifier = RControl;
useModMapMods= level1;
action= SetMods(modifiers=RControl, clearLocks);
};
interpret Control_R {
virtualModifier = RControl;
action= SetMods(modifiers=RControl, clearLocks);
};
};
(例如,您可以将上述内容保存到文件中,例如rctrlfix
,然后在其中xkb_compat { ... }
将 更改为include "complete"
。
include "complete+rctrlfix"
)
接下来,分离右控制键的修饰符映射。由于默认配置中现有的修饰符映射使用 keysym Control_R
,因此在替换修饰符映射时需要使用 keysym Control_R
;使用 key<RCTL>
将不起作用。您还需要手动清除并设置按键模拟中所需的修饰符位。因此,请在符号配置中包含以下内容:
partial alphanumeric_keys modifier_keys
xkb_symbols "rctrlarrows" {
replace key <RCTL> { [ Control_R ] }; // The default, anyway
// Bind to modifier Mod3 (instead of existing default Control)
replace modifier_map none { Control_R };
replace modifier_map Mod3 { <RCTL> };
key <UP> {
type = "PC_RCONTROL_LEVEL2",
symbols = [ Up, NoSymbol ],
actions = [ NoAction(),
RedirectKey(
key=<PGUP>,
clearMods=RControl
)]
};
key <DOWN> {
type = "PC_RCONTROL_LEVEL2",
symbols = [ Down, NoSymbol ],
actions = [ NoAction(),
RedirectKey(
key=<PGDN>,
clearMods=RControl
)]
};
key <LEFT> {
type= "PC_RCONTROL_LEVEL2",
symbols = [ Left, NoSymbol ],
actions = [ NoAction(),
RedirectKey(
key=<PGUP>,
clearMods=RControl,
Modifiers=Control
)]
};
key <RGHT> {
type= "PC_RCONTROL_LEVEL2",
symbols = [ Right, NoSymbol ],
actions = [ NoAction(),
RedirectKey(
key=<PGDN>,
clearMods=RControl,
Modifiers=Control
)]
};
};
由于修饰符映射Control_R
被第二次定义,因此可能会出现错误消息,但这似乎是无害的。
解决方案 1 的变体是Control_R
完全放弃键符,并使用一个不是修饰符且未在兼容性配置中使用的备用键符(例如Pause
),并将其解释为兼容性配置中的虚拟修饰符RControl
。也就是说,在上述配置中始终用 替换Control_R
。Pause
这也可以避免出现多个修饰符映射错误消息。
替代解决方法。
解决方案 2:通过使用基于实数修饰符的类型来绕过悬垂虚拟修饰符问题 ( Mod3
)。
如果符号配置如上所述定制为键符 (key )Mod3
的实数修饰符位,则可以通过修改类型配置(而不是修改兼容性配置,可以保持不变)来实现相同的结果:在的类型定义中,将虚拟修饰符替换为实数修饰符。(您可能希望将其放入新类型中,并在您的按键模拟中相应地更改类型名称。)Control_R
<RCTL>
PC_RCONTROL_LEVEL2
RControl
Mod3
解决方案 3:重新定义<RCTL>
为 3 级移位键符号
ISO_Level3_Shift
。
另一种解决方法(无需修改兼容性配置或类型配置)是将<RCTL>
键重新定义为 Level3 修饰键符
ISO_Level3_Shift
(而不是Control_R
)。然后使用和在第三级(而不是第二级)定义的符号/操作值定义所需的键模拟type = "THREE_LEVEL"
。这将按预期工作,因为 (a) 默认 xkb 符号配置将“假”键定义
<LVL3>
为键符,并通过修饰符映射将ISO_Level3_Shift
真实修饰符位绑定到该键符,(b) 默认 xkb 类型配置使用虚拟修饰符定义类型的 3 级移位 ,以及 (c) 默认 xkb 兼容性配置将键符解释为虚拟修饰符,因此不存在悬空虚拟修饰符问题。Mod5
THREE_LEVEL
LevelThree
ISO_Level3_Shift
LevelThree
partial alphanumeric_keys modifier_keys
xkb_symbols "rctrlarrows" {
replace key <RCTL> {
type[Group1] = "ONE_LEVEL",
symbols[Group1] = [ ISO_Level3_Shift ]
};
// Keysym ISO_Level3_Shift is bound to the real modifier bit Mod5
// in the xkb default configs in symbols/pc (via key <LVL3>)
key <UP> {
type = "THREE_LEVEL",
symbols = [ NoSymbol, NoSymbol, NoSymbol ],
actions = [ NoAction(), NoAction(),
RedirectKey(keycode=<PGUP>,
clearmods=LevelThree)
]
};
key <DOWN> {
type = "THREE_LEVEL",
symbols = [ NoSymbol, NoSymbol, NoSymbol ],
actions = [ NoAction(), NoAction(),
RedirectKey(keycode=<PGDN>,
clearmods=LevelThree)
]
};
key <LEFT> {
type = "THREE_LEVEL",
symbols = [ NoSymbol, NoSymbol, NoSymbol ],
actions = [ NoAction(), NoAction(),
RedirectKey(keycode=<PGUP>,
modifiers=Control, clearmods=LevelThree)
]
};
key <RGHT> {
type = "THREE_LEVEL",
symbols = [ NoSymbol, NoSymbol, NoSymbol ],
actions = [ NoAction(), NoAction(),
RedirectKey(keycode=<PGDN>,
modifiers=Control, clearmods=LevelThree)
]
};
};
答案2
您需要添加一个函数包装器,如下所示。
default partial alphanumeric_keys modifier_keys
xkb_symbols "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>)] };
};