如何使所有应用程序都遵守我修改过的xkb布局?


15

我不喜欢在主键盘和移动键之间跳转,所以我在xkb布局文件中添加了以下内容。

hidden partial xkb_symbols "movement"
{
    key <AD08> { [ NoSymbol, NoSymbol, Up,          Up          ] };
    key <AC08> { [ NoSymbol, NoSymbol, Down,        Down        ] };
    key <AC07> { [ NoSymbol, NoSymbol, Left,        Left        ] };
    key <AC09> { [ NoSymbol, NoSymbol, Right,       Right       ] };
    key <AD09> { [ NoSymbol, NoSymbol, Prior,       Prior       ] };
    key <AB09> { [ NoSymbol, NoSymbol, Next,        Next        ] };
    key <AB07> { [ NoSymbol, NoSymbol, Home,        Home        ] };
    key <AB08> { [ NoSymbol, NoSymbol, End,         End         ] };
    key <AC06> { [ NoSymbol, NoSymbol, Delete,      Delete      ] };
}

然后,在文件的稍后部分将它们包括到布局中。现在,我应该可以通过AltGr + j,k,l,i(或在使用dvorak时使用h,t,n,c)等来访问光标键。在许多情况下(例如Firefox,urxvt,Eclipse, LyX的主要文本区域),但是某些程序在我尝试使用这些“快捷方式”移动光标时不起作用(例如NetBeans和LyX对话框)。

那么,有没有办法使这些其他程序也尊重我的愿望?他们为什么不首先工作?我没有使用DE;只有超赞的WM。

编辑:

  • 是完整但经过简化的键盘布局文件。我有这个,/usr/share/X11/xkb/symbols/nonpop并用加载setxkbmap nonpop
  • 我注意到在MonoDevelop中,工作时可以移动,但选择时不行。也就是说,如果我按Shift + Right,则照常选择文本,但是如果我按AltGr + Shift + n,则光标只是移动而没有选择。例如,在Firefox中,两种方法均可用于选择。
  • 这里到底只讲覆盖,看起来像的东西,或许是一个解决方案,但我还没有想出如何使用它们。

1
我没有解决方案,但是如果尽管您设置了赏金,但是如果您仍然无法获得答案,则可以尝试在unix.SE(一个以Unix / Linux为中心的Stackexchange网站)上进行询问。
谷氨酰胺

Answers:


16

他们为什么不工作

根据您提到的ArchWiki的文章

  • X服务器从输入设备获取键码,并将其转换为 statekeysym

    • state是X修饰符(Ctrl / Shift / etc)的位掩码。

    • keysym是(根据/usr/include/X11/keysymdef.h)整数,

      识别与键盘布局的每个键关联的字符或功能(例如,通过可见的雕刻)。

      每个可打印字符都有自己的键符,如plusaA,或 Cyrillic_a,但其他按键也产生自己的键符,象 Shift_LLeftF1

  • 按键/释放事件中的应用程序将获取所有这些信息。

    有些应用程序会像Control_L自己一样跟踪键符,而其他应用程序只是在state中寻找修饰符位。

所以,当您按AltGr+ 时会发生什么j

  • 您按AltGr。应用程序获取KeyPress为108(<RALT>)和keyym为0xfe03(ISO_Level3_Shift)的KeyPressed事件,状态为0。

  • 按下j(在dvorak中映射为“ h”,不带修饰符)。应用程序获取KeyPress事件,其键码为44(<AC07>),键符号为0xff51(Left),状态为0x80(修改器Mod5处于打开状态)。

  • 你放开j。应用程序使用相同的参数获取键<AC07>/的KeyRelease事件 Left

  • 然后释放AltGr— AltGr的KeyRelease事件。(顺便说一下,这里的状态仍然是0x80,但这无关紧要。)

如果您运行xev实用程序,这可以看到。

因此,所有这些都意味着,尽管应用程序获得的键符号代码(Left)与普通键相同<LEFT>,但它也从AltGr获取键符号代码和修饰符状态。最有可能的是,那些不起作用的程序,请注意修改器,并且在某些程序处于活动状态时不想工作。

如何使它们工作

显然,我们不能将每个程序都更改为不寻找修饰符。那么避免这种情况的唯一选择是不生成修饰符的键符和状态位。

1.单独分组

这使我头脑的唯一方法是:在一个单独的组和开关之前按压的键定义光标移动键,一个独立的按键,该组jklihtnc)(组闭锁是优选的方法据我了解,一次组更改)。

例如:

xkb_keymap {
    xkb_keycodes { include "evdev+aliases(qwerty)" };
    xkb_types { include "complete" };
    xkb_compatibility {
        include "complete"

        interpret ISO_Group_Latch { action = LatchGroup(group=2); };
    };
    xkb_symbols {
        include "pc+us(dvorak)+inet(evdev)"

        key <RALT> { [ ISO_Group_Latch ] };

        key <AC07> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Left ]
        };
        key <AC08> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Down ]
        };
        key <AC09> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Right ]
        };
        key <AD08> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Up ]
        };
    };
    xkb_geometry { include "pc(pc104)" };
};

现在,如果您先按AltGr然后再(另外)按一个移动键,则此操作应该可以进行。

但是,这不是很有用,更合适的是LockGroup 代替闩锁并在组切换前后按AltGr。更妙的可能是SetGroup-然后将AltGr键选择该组只有在按下,但公开的应用程序的AltGr的键符(ISO_Group_Shift/ ISO_Group_Latch/任何定义)(但修改状态保持清洁)。

但是...应用程序还可能读取密钥代码(真实密钥的代码)。然后它将注意到“假”光标键。

2.叠加层

更为“低级”的解决方案将是覆盖(如同一篇文章 所述)。

重叠仅表示某个(真实键盘)键返回另一个键的键码。X服务器更改键的键码,并为该新键码计算修改器状态和键符,因此应用程序不应该注意到更改。

但是叠加层非常有限:

  • X服务器中只有2个叠加控制位(即,最多可以有2个叠加)。
  • 每个键只能有1个备用键代码。

至于其余部分,其实现与带有单独组的方法非常相似:

xkb_keymap {
    xkb_keycodes { include "evdev+aliases(qwerty)" };
    xkb_types { include "complete" };
    xkb_compatibility {
        include "complete"

        interpret Overlay1_Enable {
            action = SetControls(controls=overlay1);
        };
    };
    xkb_symbols {
        include "pc+us(dvorak)+inet(evdev)"

        key <RALT> {
            type[Group1] = "ONE_LEVEL",
            symbols[Group1] = [ Overlay1_Enable ]
        };
        key <AC07> { overlay1 = <LEFT> };
        key <AC08> { overlay1 = <DOWN> };
        key <AC09> { overlay1 = <RGHT> };
        key <AD08> { overlay1 = <UP> };
    };
    xkb_geometry { include "pc(pc104)" };
};

SetControls表示在按下键时更改控制位,并在释放键时将其恢复。应该有类似的功能LatchControls,但是 xkbcomp给我

Error:            Unknown action LatchControls

关于键映射编译。

(顺便说一句,我还使用了dvorak,并且还将一些移动键盘符号重新映射为高级的字母键。并且还遇到了一些损坏的功能(通过Ctrl-Alt-Left / Right / Right选择Xfce笔记和桌面开关)。感谢您的问题和答案,现在我知道什么是叠加层了:)。)


谢谢!实际上,我在unix.se上得到了另一个答案,起初看起来很完美,但结果发现某些应用程序仍然表现不佳。在这些情况下,此解决方案(覆盖)也适用。
2014年

我只是注意到google chrom [e | ium]也不在乎!:(幸运的是,我没有太多地使用它们。
nonpop

@nonpop Goddamn Chromium…我已在我的回复中添加了更新superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko

惊人!我已经搜索了多年!Chromium仍然存在一个小问题,它可以解释的按键Overlay1_Enable。我的症状与这里相同:github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch

1
我只是设法解决了上述问题。我的主行箭头键现在也可以在Chromium中使用!我需要对此答案进行以下更改。gist.github.com/Tarrasch/1293692/…–
Tarrasch

4

我也有同样的问题。太痛苦了

因此标题是“如何使所有应用程序都遵守我修改的xkb布局?”。好吧,我认为唯一的方法是修复所有错误执行的程序。让我们开始吧!

好吧,在报告了NetBeans中的错误(更新:我已经尝试了最新版本并且现在可以使用!)之后,我认为我将继续为每个应用程序报告此错误。列表上的下一个应用程序是Speedcrunch

但是,在寻找类似的错误报告之后,我发现了这个问题。有人遇到同样的问题,太好了!

阅读评论后,您将了解到所有QT应用程序中都应存在此错误。这是QT错误报告。尚未解决,但似乎问题已在Qt5中解决

但是,如果您查看注释,则有解决方法!下面是它的工作原理。如果您这样做:

key <SPCE> { [ ISO_Level3_Shift ] };

然后可以将其更改为:

key <SPCE> {
  type[Group1]="ONE_LEVEL",
  symbols[Group1] = [ ISO_Level3_Shift ]
};

它实际上将解决某些应用程序的问题!例如,Speedcrunch现在为我工作!好极了!

摘要

现在,任何应用程序都可以正常运行。如果不是,则必须使用type[Group1]="ONE_LEVEL"。如果已经拥有它,则必须更新软件。如果仍然无法正常运行,则它是特定于应用程序的,您必须提交错误报告。

更新(2017-09-23)

到目前为止,所有应用程序都遵循我的键盘布局。除了一个。

严重地,Chromium中的键盘处理是垃圾。它有几个问题:

  • Shift选择不使用自定义箭头键(但是箭头键本身可以正常工作)
  • 如果您有多个布局,并且在其中一个布局上某个键是特殊的(例如箭头,Backspace等),则在另一个布局上,此键将固定为您在第一个布局上所具有的键。例如,如果您有两种布局:foobar并且某个键在中执行Backspace foo,那么bar即使在其中重新定义,它也将继续作为Backspace起作用。

多年来,我一直不使用铬而忽略了这些问题。但是,如今,人们倾向于使用电子(Electron),不幸的是,电子基于铬。

解决此问题的正确方法是在Chromium中提交错误报告,并希望做到最好。我不知道他们要花多长时间才能解决仅影响几个用户的问题……但这似乎是唯一的出路。这样做的问题是铬实际上在neo(de)布局上可以正常工作。Neo布局在level5上具有箭头键,但是我无法在自定义布局中使用它。

仍未解决的错误报告:


谢谢(你的)信息!解决方法对我没有帮助,所以我想我只需要报告错误并等待qt5转换。
2015年

4

如何使它们工作-解决方案3

使用其他级别和操作RedirectKey

以下解决方案使用左Alt键在jkli上提供光标键,在uopö上提供Home / End / PageUp / PageDown,在Backspace上提供Delete键。

左Alt键可用于其他所有键(例如应用程序菜单)的其他目的。使用光标块时,左侧的Alt(Mod1)从修改器状态中删除,因此应用程序看不到它。

xkb_keymap {
    xkb_keycodes { 
        include "evdev+aliases(qwertz)" 
    };
    xkb_types { 
        include "complete"  
    };
    xkb_compat { 
        include "complete"
        interpret osfLeft {
            action = RedirectKey(keycode=<LEFT>, clearmodifiers=Mod1);
        };
        interpret osfRight {
            action = RedirectKey(keycode=<RGHT>, clearmodifiers=Mod1);
        };
        interpret osfUp {
            action = RedirectKey(keycode=<UP>, clearmodifiers=Mod1);
        };
        interpret osfDown {
            action = RedirectKey(keycode=<DOWN>, clearmodifiers=Mod1);
        };
        interpret osfBeginLine {
            action = RedirectKey(keycode=<HOME>, clearmodifiers=Mod1);
        };
        interpret osfEndLine {
            action = RedirectKey(keycode=<END>, clearmodifiers=Mod1);
        };
        interpret osfPageUp {
            action = RedirectKey(keycode=<PGUP>, clearmodifiers=Mod1);
        };
        interpret osfPageDown {
            action = RedirectKey(keycode=<PGDN>, clearmodifiers=Mod1);
        };
        interpret osfDelete {
            action = RedirectKey(keycode=<DELE>, clearmodifiers=Mod1);
        };
    };
    xkb_symbols { 
        include "pc+de(nodeadkeys)"
        include "inet(evdev)"
        include "compose(rwin)"
        key <LALT> {
            type[Group1] = "ONE_LEVEL",
            symbols[Group1] = [ ISO_Level5_Shift ]
        };
        modifier_map Mod1 { <LALT> };
        key <AC07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ j, J, dead_belowdot, dead_abovedot, osfLeft, osfLeft, osfLeft, osfLeft ]
        };
        key <AC08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ k, K, kra, ampersand, osfDown, osfDown, osfDown, osfDown ]
        };
        key <AC09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ l, L, lstroke, Lstroke, osfRight, osfRight, osfRight, osfRight ]
        };
        key <AC10> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ odiaeresis, Odiaeresis, doubleacute, doubleacute, osfPageDown, osfPageDown, osfPageDown, osfPageDown ]
        };
        key <AD07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ u, U, downarrow, uparrow, osfBeginLine, osfBeginLine, osfBeginLine, osfBeginLine ]
        };
        key <AD08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ i, I, rightarrow, idotless, osfUp, osfUp, osfUp, osfUp ]
        };
        key <AD09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ o, O, oslash, Oslash, osfEndLine, osfEndLine, osfEndLine, osfEndLine ]
        };
        key <AD10> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ p, P, thorn, THORN, osfPageUp, osfPageUp, osfPageUp, osfPageUp ]
        };
        key <BKSP> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ BackSpace, BackSpace, BackSpace, BackSpace, osfDelete, osfDelete, osfDelete, osfDelete ] 
        };
    };
    xkb_geometry { 
        include "pc(pc105)" 
    };
};

天哪!确实有效!它适用于Chromium等损坏的应用程序。您能解释一下这些osf定义吗?看来它们是预定义的,所以您不能随意命名它们。
Aleks-Daniel Jakimenko,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.