R_Control+Arrows 的 xkb 映射

R_Control+Arrows 的 xkb 映射

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没有效果的原因,这可以被视为RControlxkb 中的“悬空配置错误”。(此问题不会影响类型,PC_CONTROL_LEVEL2因为该类型不使用任何虚拟修饰符 - 它使用真实修饰符Control。)

问题 B: 需要一个单独的实修饰位来进行右控制,与修饰位不同Control

符号配置文件/usr/share/X11/xkb/symbols/pc包含:

modifier_map Control { Control_L, Control_R };

由于左控制键和右控制键都默认配置为设置修饰符Control位,因此除非通过单独的修饰符映射明确绑定到不同的修饰符位,否则它们的行为将完全相同。在这里,我们当然需要右控制键充当与左控制键不同的修饰符。例如,可以通过将右控制键的修饰符位 ( Control) 更改为不同的可用修饰符位来实现,例如Mod3Mod3在默认 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_RPause 这也可以避免出现多个修饰符映射错误消息。

替代解决方法。

解决方案 2:通过使用基于实数修饰符的类型来绕过悬垂虚拟修饰符问题 ( Mod3)

如果符号配置如上所述定制为键符 (key )Mod3 的实数修饰符位,则可以通过修改类型配置(而不是修改兼容性配置,可以保持不变)来实现相同的结果:在的类型定义中,将虚拟修饰符替换为实数修饰符。(您可能希望将其放入新类型中,并在您的按键模拟中相应地更改类型名称。)Control_R<RCTL>PC_RCONTROL_LEVEL2RControlMod3

解决方案 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 兼容性配置将键符解释为虚拟修饰符,因此不存在悬空虚拟修饰符问题。Mod5THREE_LEVELLevelThreeISO_Level3_ShiftLevelThree

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>)] };
};

相关内容