R_Control+Arrows 的 xkb 映射

Jas*_*B42 6 keyboard-layout xkb 17.10

有一台带有方向箭头键和/ / / 的Fn+ 箭头的笔记本电脑。想要制作这些键,以便 Right Control 将它们更改为:PageUpPageDownHomeEnd

  • 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>)] };
Run Code Online (Sandbox Code Playgroud)

问题:

不幸的是,上面的脚本捕获了两个 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)使用 virtual 修饰符RControl。为了使虚拟修饰符 RControl执行我们期望的操作,它应该Control_R通过 interpret中的节与实际的键符号相关联/usr/share/X11/xkb/compat/pc。但 virtual 修饰符RControl根本不与任何键符号关联,实际上它没有在兼容性配置中以任何方式设置:不 grep RControl /usr/share/X11/xkb/compat/*返回任何内容。这就是为什么您发现PC_RCONTROL_LEVEL2没有效果,这可以被认为是RControlxkb 中的“悬空配置错误”。(此问题不会影响类型PC_CONTROL_LEVEL2,因为该类型不使用任何 virtual 修饰符 - 它使用 real 修饰符Control。)

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

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

modifier_map Control { Control_L, Control_R };
Run Code Online (Sandbox Code Playgroud)

由于左控制键和右控制键默认都配置为设置修饰符Control位,因此除非通过单独的修饰符映射显式绑定到不同的修饰符位,否则它们的行为相同。这里我们当然需要右控制键作为与左控制键不同的修饰符。例如,可以通过将右控制键的修饰符位 ( Control) 更改为不同的可用修饰符位(例如Mod3Mod3不绑定到默认 xkb 配置中的任何键)来完成此操作。

以下是解决这两个问题的三种方法。

解决方案 1:修复RControl.

下面的解决方法实现了您所需的设置(在我的测试中)。

首先,在 xkb 兼容性配置中包含以下内容,以将Control_Rkeysym 解释为虚拟修饰符 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);
  };

};
Run Code Online (Sandbox Code Playgroud)

(例如,您可以将以上内容保存到文件中,例如rctrlfix,然后在 中将xkb_compat { ... }更改为include "complete"include "complete+rctrlfix"

接下来,分离右控制键的修饰符映射。由于默认配置中现有的修饰符映射使用 keysym ,因此 在替换修饰符映射时Control_R需要使用 keysym ;Control_R使用该密钥<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
                        )]
    };

};
Run Code Online (Sandbox Code Playgroud)

由于 的 修改器映射Control_R是第二次定义的,因此可能会出现一条错误消息,但这似乎无害。

解决方案 1 的一个变体是Control_R 完全放弃键符,并使用一个备用键符代替它,该键符不是修饰符且未在兼容性配置中使用(例如Pause),并将其解释为RControl兼容性配置中的虚拟修饰符。即, 在上述配置中替换Control_R为through。Pause这也可以避免多重修饰符映射错误消息。

替代解决方法。

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

如果符号配置按照上面的方式自定义,作为键符号 (key )Mod3 的真实修饰符位,那么可以通过修改类型配置来实现相同的结果(而不是修改兼容性配置,可以保持不变):的类型定义,将 virtual 修饰符替换为 real 修饰符。(您可能希望将其放入新类型中,并在密钥模拟中相应地更改类型名称。)Control_R<RCTL>PC_RCONTROL_LEVEL2RControlMod3

解决方案 3:重新定义<RCTL>为 3 级移位器 keysym ISO_Level3_Shift

还有另一种解决方法(无需触及兼容性配置或类型配置)是将键重新定义<RCTL>为 Level3 修饰键符号 ISO_Level3_Shift(而不是Control_R)。type = "THREE_LEVEL" 然后使用第三级(而不是第二级)定义的符号/操作值来定义所需的按键模拟。这将按预期工作,因为(a)默认的 xkb 符号配置将“假”键定义 <LVL3>为键符号,并通过修饰符映射将ISO_Level3_Shift真实修饰符位绑定到它,(b)默认的 xkb 类型配置定义了type 的使用虚拟修饰符进行级别 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)
                    ]
    };

};
Run Code Online (Sandbox Code Playgroud)


小智 0

您需要添加一个函数包装器,如下所示。

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>)] };
};
Run Code Online (Sandbox Code Playgroud)