如何在xkb中制作ISO_Level4_Shift并锁定?

如何在xkb中制作ISO_Level4_Shift并锁定?

我想知道是否可以在 xkb 中将键设置为 4 级修改器或储物柜,而不是使用:Shift + ISO_Level3_Shift(又名 AltGr)。

与 6、7 和 8 级相同的问题(使用“EIGHT_LEVEL”或变体)。

既然3级和5级都可以,那为什么其他的就不行呢?

答案1

这是可能的,但有点hacky。尚未定义特定的键符号。 ISO_Level3_{Shift,Latch,Lock}(以及 level5 的三个相同)在编译时在 X11 和 libxkbcommon 标头中定义。

compatibility在运行时,它们通过interpret节和actions;在模块中激活。例如,检查您当前的键盘映射:

$ xkbcomp $DISPLAY - | less

//....
xkb_compatibility "complete+ledcaps(shift_lock)" {
    //....
    interpret ISO_Level3_Shift+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= SetMods(modifiers=LevelThree,clearLocks);
    };
    interpret ISO_Level3_Latch+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
    };
    interpret ISO_Level3_Lock+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= LockMods(modifiers=LevelThree);
    };
    //....
    interpret ISO_Level3_Shift+AnyOfOrNone(all) {
        action= SetMods(modifiers=LevelThree,clearLocks);
    };
    interpret ISO_Level3_Latch+AnyOfOrNone(all) {
        action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
    };
    interpret ISO_Level3_Lock+AnyOfOrNone(all) {
        action= LockMods(modifiers=LevelThree);
    };
//....

有一个现有的ISO_Level2_Latch键符号。它没有interpret像上面这样的现有兼容性节,但如果您添加它们,它会按您的预期运行。 (Shift已经存在,所以ISO_Level2_Shift没有必要;Shift_Lock或者Caps_Lock取代ISO_Level2_Lock。) 因此,如果您想要一个Shift_Latch键,请使用ISO_Level2_Latch键符号并将它们添加到您的键盘映射中:

    interpret ISO_Level2_Latch+AnyOf(all) {
        useModMapMods=level1;
        action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
    };
    interpret ISO_Level2_Latch+AnyOfOrNone(all) {
        action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
    };

我们可以在 4、6、7 和 8 级使用这种方法,但没有预定义的键符号ISO_Level4_Shift等。您可以将它们添加到代码中并重新编译,或者您可以重新利用一些未使用的键符号并将其解释为 4 级移位(或闩锁或锁定)。检查头文件,libxkbcommon我们发现 XKB 知道的所有键符号名称;这些看起来可能适合我们的目的:

//....in xkbcommon/xkbcommon-keysyms.h:
//....
#define XKB_KEY_ISO_Fast_Cursor_Left          0xfe2c
#define XKB_KEY_ISO_Fast_Cursor_Right         0xfe2d
#define XKB_KEY_ISO_Fast_Cursor_Up            0xfe2e
#define XKB_KEY_ISO_Fast_Cursor_Down          0xfe2f

删除XKB_KEY_前缀以获取我们可以在 XKB 规则中引用的键符名称。让我们用ISO_Fast_Cursor_Leftfake ISO_Level4_Latch

首先,生成一个基本的键盘映射,带有setxkbmap -print;然后我们将编辑此文件并向其添加覆盖,最后使用以下命令加载更改后的键盘映射xkbcomp [file] $DISPLAY

$ setxkbmap -print > mykeymap.xkb
xkb_keymap {
    xkb_keycodes  { include "evdev+aliases(qwerty)" };
    xkb_types     { include "complete"  };
    xkb_compat    { include "complete"  };
    xkb_symbols   { include "pc+us(altgr-intl)+inet(evdev)" };
    xkb_geometry  { include "pc(pc105)" };
};

现在编辑此文件并将我们需要的覆盖放入其中:

// Attempting to define and use a key as Level4 Shift/Latch/Lock.
// Plan: * activate lv5 shift on rctrl.
//       * place latches on lv5 of keys 2,3,4,5 for corresponding level.
//       * replace keys ASDF with 8-level versions and define symbols for test.
//       * pressing RCtrl+4 then A should result in Á

// starting point: setxkbmap -layout us -variant altgr-intl -option '' -print
// load this file: xkbcomp myfile.xkb $DISPLAY
xkb_keymap {
    xkb_keycodes  { include "evdev+aliases(qwerty)" };
    xkb_types     { include "complete"      };
    xkb_compat    { 
        include "complete"      

        // add in interpretations
        // ISO_Level3_Latch includes a +AnyOf stanza and a +AnyOfOrNone stanza (same for ISO_Level5_Latch)
        // assume each additional latch needs both
        interpret ISO_Level2_Latch+AnyOf(all) {
            useModMapMods=level1;
            action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
        };
        interpret ISO_Level2_Latch+AnyOfOrNone(all) {
            action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
        };
        interpret ISO_Fast_Cursor_Left+AnyOf(all) {
            // Level4 needs both Shift and LevelThree
            useModMapMods=level1;
            action= LatchMods(modifiers=Shift+LevelThree,clearLocks,latchToLock);
        };
        interpret ISO_Fast_Cursor_Left+AnyOfOrNone(all) {
            // Level4 needs both Shift and LevelThree
            action= LatchMods(modifiers=Shift+LevelThree,clearLocks,latchToLock);
        };
    };
    xkb_symbols   { 
        include "pc"
        include "us(altgr-intl)"
        include "inet(evdev)"

        // latch keys
        key <AE02> {
            type= "EIGHT_LEVEL",
            symbols[Group1]= [ 2, at, twosuperior, dead_doubleacute, ISO_Level2_Latch, X, z, Z ]
        };
        key <AE03> {
            type= "EIGHT_LEVEL",
            symbols[Group1]= [ 3, numbersign, threesuperior, dead_macron, ISO_Level3_Latch, X, z, Z ]
        };
        // no ISO_Level4_Latch so use ISO_Fast_Cursor_Left
        key <AE04> {
            type= "EIGHT_LEVEL",
            symbols[Group1]= [ 4, dollar, currency, sterling, ISO_Fast_Cursor_Left, X, z, Z ]
        };
        key <AE05> {
            type= "EIGHT_LEVEL",
            symbols[Group1]= [ 5, percent, EuroSign, dead_cedilla, ISO_Level5_Latch, X, z, Z ]
        };
        // no ISO_Level6_Latch so use ISO_Fast_Cursor_Right
        // no ISO_Level7_Latch so use ISO_Fast_Cursor_Up
        // no ISO_Level8_Latch so use ISO_Fast_Cursor_Down

        // eight-level keys ASDF for testing
        key <AC01> {
            type= "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1]= [ a, A, aacute, Aacute, agrave, Agrave, aring, Aring ]
        };
        key <AC02> {
            type= "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1]= [ s, S, ssharp, section, ccedilla, Ccedilla, ntilde, Ntilde ]
        };
        key <AC03> {
            type= "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1]= [ d, D, eth, ETH, thorn, THORN, t, T ]
        };
        key <AC04> {
            type= "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1]= [ f, F, eacute, Eacute, x, X, z, Z ]
        };

        // ISO_Level3_Shift on Right Alt
        include "level3(ralt_switch)"
        // ISO_Level5_Shift on Right Ctrl
        include "level5(rctrl_switch)"  
    };
    xkb_geometry  { include "pc(pc105)"     };
};

现在您可以测试锁存器(在上面的示例中,ISO_Level5_Shift应该是右键Ctrlxkbcomp如果不是,请重新运行命令):

  • ISO_Level5_Shift+2那么a应该打印A
  • ISO_Level5_Shift+3那么a应该打印á
  • ISO_Level5_Shift+4那么a应该打印Á
  • ISO_Level5_Shift+5那么a应该打印à

在测试中,我注意到 RCtrl-as-level5-shift 有点不稳定,并且并不总是能正确应用。通常重新运行该xkbcomp命令一两次即可使其正常工作。用AF键进行测试;Ctrl+D可能会退出你的 shell。


有些应用程序无法识别我们借用的键盘符号,并且可能会做出奇怪的事情。例如,Firefox 将4在激活正确的锁存器时打印偶数,因此按键顺序rctrl+4 then a会导致;对于 3 和 5 上的真实键盘符号来说,这种情况不会发生,所以也许借用不同的键盘符号会让 Firefox 认识到不应该打印任何内容。到目前为止,大多数终端应用程序都按预期运行。

答案2

我遇到了同样的问题,并找到了一种更直接的方法来做到这一点。我的用例是只需按一键即可获得到 7 级的快捷方式,该方法非常通用,不是 hack。

对于额外的关卡名称,除了已经使用的 Shift、LevelThree 和 LevelFive 之外,我们还可以使用虚拟修饰符 Super 或 Hyper(或 Meta)。我将在级别 7 中使用 Hyper。 Super 和 Hyper 的解释在 /usr/share/X11/compat/misc 中定义,并且它们包含在默认配置中。

要添加额外的快捷方式,我们将创建一个新的类型。通常用于八个级别的类型是 EIGHT_LEVEL,并在 /usr/share/X11/xkb/types/level5 中定义。创建一个名为 level7_hyper 的文件,其中包含以下内容并将其保存在 /usr/share/X11/xkb/types 中。如果我们愿意,我们可以为同一级别设置多个组合键。

default partial xkb_types "default" {

// Adds the shortcut Hyper to reach level 7
// and Hyper+Shift to reach level 8

virtual_modifiers  LevelThree, LevelFive, Hyper;

type "EIGHT_LEVEL_HYPER" {
modifiers = Shift + LevelThree + LevelFive + Hyper;
map[None] = Level1;
map[Shift] = Level2;
map[LevelThree] = Level3;
map[Shift+LevelThree] = Level4;
map[LevelFive] = Level5;
map[Shift+LevelFive] = Level6;
map[Hyper] = Level7;
map[LevelThree+LevelFive] = Level7;
map[Shift+Hyper] = Level8;
map[Shift+LevelThree+LevelFive] = Level8;
level_name[Level1] = "Base";
level_name[Level2] = "Shift";
level_name[Level3] = "Alt Base";
level_name[Level4] = "Shift Alt";
level_name[Level5] = "X";
level_name[Level6] = "X Shift";
level_name[Level7] = "X Alt Base";
level_name[Level8] = "X Shift Alt";
};
};

要在符号文件中使用此类型,请修改此最小工作示例。将其保存为例如 /usr/share/X11/xkb/symbols/level7se。

default partial alphanumeric_keys
xkb_symbols "level7se" {
// Include your favourite symbols
include "se" 

name[Group1]="Level7-se";
key.type[Group1] = "EIGHT_LEVEL_HYPER";

// Copy in the lines from the symbols file of your choice and make
// your edits, here just the button A
key <AC01>  { [ a, A, b, B, c, C, d, D ]}; 

// Modifier keys only have one level
key.type[Group1] = "ONE_LEVEL";

// Right Alt gives level 3
key <RALT> {[ ISO_Level3_Shift ]};

// Left Win key gives level 5 
key <LWIN> {[ ISO_Level5_Shift ]};

// The button to the left of the number line (paragraph on Swedish 
// keyboards. Tilde on some others?) gives level 7.
key <TLDE> {[ Hyper_R ]};    
};

然后您可以使用以下命令加载配置

setxkbmap -types complete+level7_hyper level7se

我们还需要包含完整的类型,因为修饰键使用 ONE_LEVEL 类型。

要获得更多级别的快捷方式,只需将相应的行添加到类型文件并将相应的部分添加到符号文件。

相关内容