在Ubuntu 13.04中设置永久的xmodmap配置

我无法在Ubuntu 13.04上登录时运行xmodmap。我已经搜索过了,包括在askubuntu上,但找到的所有答案都不起作用。
我在我的主文件夹中有一个名为.Xmodmap的文件,其中包含所需的映射。如果我手动运行它,它可以正常工作,所以没有错误。为了让它在启动时运行,我尝试了以下方法:
1. 使用各种包含以下命令的.xinitrc文件: - xmodmap .Xmodmap - xmodmap ~/.Xmodmap - /usr/bin/xmodmap /home/NAME/.Xmodmap - if [ -s ~/.Xmodmap ]; then xmodmap ~/.Xmodmap fi
2. 使用.Xresources代替.xinitrc,并使用相同的变体。
3. 将其设置为启动应用程序。
以上方法在Ubuntu 13.04(64位)上均无效。我还看到一些关于全局更改键盘映射的想法,但大多数在Ubuntu 13.04中不适用(即指定位置不存在相应文件),而且我也不愿意触碰全局设置。
11个回答

Ubuntu不再使用xmodmap,而是使用xkb(据我了解,这可以方便每个窗口使用不同的键盘布局等等)。
系统级别的映射文件位于...
/usr/share/X11/xkb/symbols/

地图似乎是按层次加载的,以pc地图作为根,而任何语言(例如en)作为根的子级。
在我的特殊情况下,我在键盘上物理交换了Page Up和Home,以及Page Down和End,所以我粗略地对系统范围内的pc地图进行了以下更改:
 key <HOME> {    [  Prior        ]   };
 key <PGUP> {    [  Home         ]   };
 key  <END> {    [  Next         ]   };
 key <PGDN> {    [  End          ]   };

注意:为使Xorg使用您的新键盘映射,您可能需要删除现有的预编译映射(*.xkm)中的文件

/var/lib/xkb/

然后重新启动Xorg。
关于xkb有各种资源可供参考,但这个与Ubuntu相关。

13从Ubuntu 14.04开始,这是最简单的交换按键的方法。你可以通过将xmodmap添加到启动应用程序来使其在登录时运行,但如果你暂停、休眠等,你必须手动启动它或创建启动守护进程脚本。 - holocronweaver
1我可以根据修饰键重新映射按键:未修改 Shift AltGr* Shift+AltGr。但是左Alt超级键呢? - Farzher
9我不认为你的第一句话是正确的。你有任何来源吗?我很难相信“Ubuntu的方式”重新映射键盘会通过编辑xkb中的键盘映射来实现。除了晦涩难懂之外,这种方法还存在一个问题,就是当xkb更新时,你的自定义映射会被删除。 - Mateus Araújo
1话虽如此,这是我在Ubuntu上找到的唯一可靠的按键重映射方法。 - Mateus Araújo
2一定有更好的方法。我知道我想映射的确切按键码,但是217按键码甚至在xkb中都没有列出。我甚至看不到添加新按键码的方法。 - Jonathan
这个方法是有效的,但是如何在重启后保持这些更改不变呢? - Ayush Goyal
为什么它们会在重新启动时有所不同?该文件每个会话只加载一次。除非有什么改变它的因素,否则它每次都会保持相同。 - underscore_d
要查看当前使用的所有符号和按键代码,请执行xkbcomp $DISPLAY myFile命令。 - phil294
什么是xkb?我的Ubuntu 16上没有安装它。 - Yan King Yin
要重新启动Xorg,请参阅:https://askubuntu.com/questions/1220/how-to-restart-x-window-server-from-command-line - Vesanto
在Ubuntu 18.04 LTS上,我无法按照这个过程进行操作。我是不是漏掉了什么明显的东西?我在符号文件夹中找不到"en"的任何地方。 $ ls -R /usr/share/X11/xkb/symbols/ | grep -i en 给出了这个结果:parens - Johan
2就我而言,在19.10版本下,基于evdev的解决方案持续有效,详见https://askubuntu.com/a/1161870/835198。 - Mario
有没有向后兼容选项?可以将现有的“xmodmap”文件转换成“xkb”吗? - personal_cloud

对我来说,如果你想要重新映射一个或两个按键,并且这种映射在系统设置中无法实现,使用xkb配置就太复杂了。此外,解决方案应该保持在用户端进行,而不是编辑'/usr/share/X11/xkb/symbols/'等文件。强制使用“启动应用程序”加载'xmodmap ~/.Xmodmap'只能在暂停、切换用户或更改键盘布局之前有效。因此,正如holocronweaver建议的那样,我根据我找到的代码片段编写了一个Python脚本,在会话启动时加载,并在需要时重新加载'~/.Xmodmap'。
请查看错误报告 #1243642(第6条评论)和在这里下载

2截至15.10仍在工作 :-) 谢谢! - lalomartins
1这个传说中的脚本链接似乎已经失效了。有人可以把它放到GitHub上吗? - Epigene
1很好 - 也是唯一可行的答案!在16.04版本中工作。为了使其在Python3中工作,将"import gobject"更改为"from gi.repository import GObject as gobject"。 - Craig Hicks
2@Epigene - 现在链接已经放上了 - Craig Hicks
1赞美之词!一个天才的解决办法。 - dmanexe
1过了一会儿,我正在使用Ubuntu 19.04。看起来我的脚本还在工作,但是:你找到其他方法了吗?因为现在我的脚本导致了感知延迟。 - dedalu
请注意,xkb 在您插入新键盘(或切换 KVM 开关)时,即使您保持登录状态也可能会清除您的 xmodmap。 - personal_cloud
@personal_cloud 这听起来像是我可能遇到的问题。我的蓝牙键盘有时会在闲置时进入睡眠状态,需要重新连接,此时 xmodmap 映射就会丢失。 - NeilG

我在Ubuntu 14.04遇到了这个问题,并在这里找到了解决方案。显然,在登录后,Ubuntu不能立即配置键盘,而是稍晚一些。因此,如果你添加一个命令
sleep 4 && xmodmap ~/.Xmodmap &

将内容翻译为中文:将代码添加到~/.bash_profile文件,然后应该可以正常运行(我用这个方法是有效的)。
编辑:这似乎只适用于登录后,而不是启动后。我稍后需要调查这个问题。

1挂起/休眠后有没有设置成功运行的好运? - Jonathan
不好意思,可惜的是我在启动后仍然无法使它工作。所以每次启动时,我都会打开终端并键入“xmodmap ~/.Xmodmap” :( - dremodaris
请注意,在Ubuntu 16.04上应使用.profile文件。 - Vitor Abella

Caps Lock 键映射为 Esc 以供 vim 使用

这是我自己的键映射启动脚本变体。它可以将任何键盘上的 Caps Lock 键映射为 Esc,以便在使用 vivimgvim 时使用。

q4w56 的回答不同,这个回答不使用任何无限循环的 while; do。否则,我的双核 CPU 中的一个核心会每5秒钟占用42%的资源,严重降低我的笔记本电池电量。

#!/usr/bin/env bash
sleep 4
xmodmap -e "clear Lock"
xmodmap -e "keysym Caps_Lock = Escape"

将其保存为脚本。使用chmod +x命令使文件可执行。 将脚本名称和位置添加到Session and Startup → Application Autostart(在Xubuntu中)。
此用户的键盘行为将在重启和注销后保持不变,但在暂停时不会保持。可以实现通过暂停实现持久性,但不幸的是只能在系统级别上实现,而不能轻松地在用户级别上实现。

编辑

我放弃了上述解决方案,转而选择这个解决方案,除了在CapsLock上提供Esc功能外,还提供箭头键和键PgUpHomeEndPgDn,分别通过CapsLock+HJKLCapsLock+UIOP实现。

对键盘重新映射的理由

在当今的计算机世界中,Caps Lock 键几乎没有什么用处了。一般来说,应该避免使用 全大写,这是基于网络礼仪表现与内容的分离的原则。此外,在使用 vim 编辑文本时,意外按到 Caps Lock 键并不总是立即注意到,但却会导致后续出现相当 恼人的 vim 行为。将 Caps Lock 键禁用,并重新映射为易于触及的 Esc 键,对于使用 vim 来说是双赢的。


替换Caps Lock键的功能可能对于没有Esc键的Apple MacBook上的vim用户来说是一个真正的救命稻草。 - Serge Stroobandt
3最好将capslock键重新映射为ctrl键。这样可以解决更多问题,在Vim中,你可以使用capslock + [来代替Esc键。不好意思插嘴,但我觉得有必要提出这个建议。 - Dmitry Koroliov
什么是“挂起”?是指关闭笔记本电脑的盖子吗?然后你的解决方案就不起作用了?在关闭笔记本电脑盖子后,如何使用vim? - Marko Avlijaš
1当你合上笔记本电脑盖子后,如何使用vim呢?当然是打开盖子! - Serge Stroobandt
哈哈,我从来没有猜到。我的意思是大写锁定键不再映射到Esc键了吗? - Marko Avlijaš
@MarkoAvlijaš “我的意思是大写锁定键不再映射到Esc键了吗?” — 没错。 - Serge Stroobandt

@Daniel的回答给了我正确的方向,但我想进一步扩展一下。
在Linux Mint 17.2和Ubuntu 16.04上对我有效。
我尝试了所有我能想到的方法来继续使用xmodmap,但当系统进入睡眠模式时,它们都失败了。即使是在启动应用程序脚本中使用setxkbmap的情况下,也会出现相同的问题,因为*settings-daemon(对我来说是xfce4)运行的时间比脚本晚---而且顺序实际上无法影响。
最后我想到了以下解决方案:
1)编写一个最小的键盘映射文件放在/usr/share/X11/xkb/symbols目录下。我们称这个文件为mylayout。它可以非常简单,例如:
xkb_symbols "basic" {
  name[Group1] = "My Layout";
  include "us"
  key <AE03> { [ 3, numbersign, sterling, sterling] };
  include "level3(ralt_switch)"
}
  • basic只是一个名称,我们以后会再次遇到它。
  • name[Group1]看起来也只是一个名称,但以后不会起任何作用。
  • include "us"包含了普通的美式键盘。实际上,us是同一目录下的另一个文件。这是我们正在适应的键盘布局。根据需要选择其他布局。注意:此行不需要分号结尾。
  • key行是键盘的一种适应方式,可以有更多的适应方式。在/usr/share/X11/xkb/keycodes文件夹中可以找到<AE03>。使用xev程序查找“3”键的键码为12,在keycodes文件Xfree86中映射为<AE03>
  • 最后,另一个include指令来激活另一个键盘选项,这里我想让右Alt键成为第三级换挡键,即可以访问我上面定义的sterling符号的键。 level3只是同一文件夹中的一个文件名,其中包含了ralt_switch的一个部分。四处看看,选择您需要包含的内容。
2) 我没有将mylayout放入系统文件夹中。相反,我只是从系统文件夹创建了一个软链接到我喜欢的文件夹,以便立即看到这不是原始软件。
3) 此外,我没有修复evdev.xml,以避免更新麻烦。但是,在键盘配置编辑器中找到mylayout是必要的(对于xfce4来说,它是xfce4-keyboard-settings)。相反,我使用了xfce4-settings-editor,并将keyboard-layout->XkbLayout更改为mylayout(文件名),将XkbVariant更改为basic(参见上文)。之后,在键盘设置编辑器中也会显示mylayout/basic。似乎只有在evdev.xml中添加条目才能选择布局。
这样,键盘设置现在可以在睡眠模式和重启后保留。

更多背景信息可以在这里找到:http://www.charvolant.org/~doug/xkb/html/node5.html

另一种解决睡眠模式问题的方法(我自己没有尝试过),可以在这里找到:https://www.vinc17.net/unix/xkb.en.html

更新:在我按照上述描述在xfce4-settings-editor中更改设置的同时,与Mint 18.3一起工作。

更新:在使用gdm3作为显示管理器和XFCE4作为窗口管理器的18.04版本中,看起来~/.Xmodmap再次被读取,并且设置似乎能够在暂停后保留。(我很少使用暂停功能,所以从来不确定笔记本电脑处于哪种模式。)


在19.10版本上,我的.Xmodmap似乎无法在暂停后保留下来... - rogerdpack

我在Ubuntu 16.04上也遇到了fcitx的问题,并在fcitx wiki上找到了解决方案,但需要fcitx版本为4.2.7或更高。
  • touch ~/.Xmodmap
  • 编写配置文件
  • 重新启动,fcitx将尝试自动加载它
还有一些关于原因的解释。

1虽然这个回答在理论上可能解决了问题,但最好还是在这里包含回答的关键部分,并提供链接作为参考。 - Videonauth
@Videonauth 我已经修改了我的回答 - Bluethon
非常感谢您 :) 我仍然在这里留下我的评论,这样在审核队列中的人们就可以看到您做了一些改变。 - Videonauth
@Videonauth 这是我的第一个回答,我的英语不好,所以可能有些错误。谢谢你的建议。:P - Bluethon
不客气。提供答案是为社区做出贡献的好方式。 - Videonauth

修订

2018年初的一次更新破坏了持久性 -- 在暂停或休眠后自动重新加载键盘映射。由于使用/etc/pm/sleep.d脚本的方法停止工作(已弃用?),只剩下较新的方法,即使用/lib/systemd/system-sleep和稍微不同的脚本(这种方法可以在键盘映射上正常工作)。

因此,本文已更新为较新的持久性方法,并包括正常的初始键盘映射加载,这也开始起作用。将.Xmodmap文件转换为.xkbmap文件的过程保持不变。

请注意,这是一个针对每个用户的解决方案。有关每个设备的答案,请参阅如何将键盘映射应用于单个设备。这种方法可以适应此处的使用。

首先根据需要修改.Xmodmap文件。直接编辑这些文件比编辑.xkbmap文件更容易。当加载完成时:

xmodmap .Xmodmap

然后将其转换为.xkb文件:

xkbcomp $DISPLAY $HOME/.xkbmap

要在启动时自动加载,请打开“启动应用程序”,点击“添加”,在命令行中输入:

``` xkbcomp /home/user/.xkbmap ":0" ```
("user" 替换为实际用户名)。对于名称,可以输入“加载键盘映射”。如有需要,添加注释并保存。
键位图将在系统启动时加载,但在挂起或休眠后将无法保留。为此,在 /lib/systemd/system-sleep 中创建一个新文件,例如命名为 60_xkbmap,其中包含以下内容:
#!/bin/sh
case $1/$2 in
  pre/*)
    # Place pre-suspend commands here
    exit 0
    ;;
  post/*)
    # Place post-suspend commands here
    export DISPLAY=":0"
    export XAUTHORITY="/home/user/.Xauthority"
    su user -c "xkbcomp /home/user/.xkb/xkb-map $DISPLAY 2>/dev/null"
    ;;
esac

参考文献)如上所述,将“user”替换为实际用户名。
关键映射现在应该自动加载并保持持久。注意:
  • 适用于当前的LTS版本16.04,以及可能的后续版本。
  • 取自上述链接错误线程的第14篇帖子
  • 早期评论适用于原始帖子。

我现在正在尝试这种方法,当我启动终端时,会收到一堆类似以下的消息: 警告:未为<AB11>(键码97)定义符号 警告:未为<JPCM>(键码103)定义符号 警告:未为<I120>(键码120)定义符号 ...... 还有很多 还不确定那会有什么后果。有人知道吗? - lost baby
尽管上述警告,这种方法确实有效,但只是暂时的 - 过一会儿,映射就会被遗忘,超级键会恢复到默认功能。所以我会尝试另一种方式 - 我会将我的Mac上的基本编辑快捷键重新映射为使用Control键而不是Command键,看看是否有效。我只希望在Mac和Ubuntu上能够使用相同的剪切-复制-粘贴-撤销-重做命令。每次我尝试复制或粘贴东西时,Ubuntu弹出搜索菜单,让我非常沮丧。 - lost baby

在接受的答案中提到的步骤(也在这里描述)是一种持久性解决方案,但在修改字母键时对我无效。
如果您尝试了其他选项或想节省时间,可以尝试文章中提到的步骤 - https://medium.com/@saplos123456/persistent-keyboard-mapping-on-ubuntu-using-xmodmap-cd01ad828fcd
  1. 创建一个xmodmap的新副本。
xmodmap -pke > .Xmodmap

编辑新文件时,请使用以下命令并根据您的需求更改密钥代码。
gedit .Xmodmap

激活这些更改。在此之后,新的更改应该会反映出来。
xmodmap .Xmodmap

4. 可跳过的步骤 - 生成具有新映射的xkb文件
xkbcomp $DISPLAY $HOME/.xkbmap

所有上述更改都是暂时的,在重新启动后将被替换。创建一个start-up program来触发以下命令。
xkbcomp /home/user/.xkbmap ":0"   // if you followed the 4th step
OR
xmodmap .Xmodmap    // if you skipped the 4th step

这也让我在从Ubuntu 12.04升级到13.04时遇到了困难。
幸运的是,现在(或者可能一直以来)可以很容易地在键盘首选项中找到这个设置,并且只需几次点击鼠标即可更改。
1. 进入“系统设置” > “键盘布局” > “选项...” 2. 在键盘布局选项中,点击箭头以显示“▸ Ctrl键位置”的选项。 3. 在“交换Ctrl和Caps Lock”处打上勾。
就这样:左侧的Control和Caps Lock已经互换位置了。
别忘了在完成更改后删除“~/.Xmodmap”文件。

这可能被投票否定是因为它没有涉及到xmodmap,但事实上,正是通过这种方式我发现使用Gnome Tweak可能是导致我的一些映射出现问题的原因。 - dragon788
我在16.04版本中没有看到这个功能,这还能实现吗? - chrismarx
1@chrismarx 不是的,他们已经移除了它。现在(16.04)我在/etc/default/keyboard中设置了XKBOPTIONS="ctrl:swapcaps" - glts

大多数其他解决方案在会话启动时(或更早)加载xmodmap,但是当您插入新的键盘(或切换KVM开关)时,您的设置会被清除。这里有一个解决方案,在您插入USB设备后重新安装xmodmap。自从Linux引入所有Alt/Meta混淆(大约在2006年)以来,我一直在使用它。
! ~/.Xmodmap file
!
! Part 1 (since about 2006)

! Avoid BadValue (TODO: debug why we get BadValue otherwise)
clear mod1
clear mod4

! Actually, my keyboard doesn't have 0xcc/0xcd keys, thank you...
keycode 0xcc = NoSymbol
keycode 0xcd = NoSymbol

! mod3 is Alt. I'm sure this is documented somewhere.
! It works that way in every program!
add mod3 = Alt_L
add mod3 = Alt_R

! In addition to Alt keys, my keyboard has ... drumroll ... *Windows* keys!
! These are *Meta* keys. Say, in Windows web browsers.
!   Don't take my word for it, hit F12 and type:
!   onkeydown = function(e){console.log(e);}
! And, um, Alt is already taken, so obviously Meta = Windows key.
! Also Windows keys = Meta in some FreeBSD distros out of the box.
! Is Windows keys = Meta not clear to someone, or is someone just being annoying
! with all this "Alt = Meta" garbage?
keycode 0x85 = Meta_L
keycode 0x86 = Meta_R

! No, mod1 is not Alt!
! In every program, mod1 is actually meta!
add mod1 = Meta_L
add mod1 = Meta_R
remove mod1 = Alt_L
remove mod1 = Alt_R



! Part 2 (since about 2015)
! What is going on?? USB thinks it can just wipe my xmodmap???
!
! 1. Locate xkb rulefile using
!
!   udevadm control --log-priority=info
!
!
! It will be something like
!
!    /lib/udev/rules.d/64-xorg-xkb.rules
!
!
! 2. Edit /lib/udev/rules.d/64-xorg-xkb.rules. Add:
!
!   RUN += "/big/usb_fix.sh"
!
! and do:
!
!   udevadm control --reload-rules
!
! note: using /big is intentional... on new Ubuntus, the system dies
! with "a start job is running..." in disk mounting. So we prevent this
! script from running ig /big is not mounted yet.
!
!
! 3. Create the /big/usb_fix.sh script:
!
! #!/bin/sh
! echo "xmodmap ~/.Xmodmap" >> /usr/local/usb_fix.log
!
! and make it executable.
! 
! 
! 4.
! mkfifo /usr/local/usb_fix.log 
! 
! 
! 5.
! Create a script (e.g. named ~/bin/usb_fix_client)
! 
! #!/bin/sh
! yes 'cat /usr/local/usb_fix.log | sh' | sh
! 
! and put this in your .xinitrc.


! Part 3 (since about 2018)
!
! Every now and then, apt-get can overwrite the xorg-xkb-rules?
! solution for now is turn off automatic updates.

如果你已经正确设置了,xmodmap应该显示如下内容:
shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Meta_L (0x85),  Meta_R (0x86)
mod2        Num_Lock (0x4d)
mod3        Alt_L (0x40),  Alt_R (0x6c)
mod4      
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

而且,你的meta和alt键现在可以正常工作了!
如果很难找到并关闭一直覆盖你的USB规则的软件(对我来说,有些软件每年会破坏它大约两次),那么只需添加一个RC脚本来复制你的USB规则回来。此外,你还可以将改进后的规则复制到一个数字更大的文件中,以便在未来覆盖其他可能破坏你的xmodmap的变化。

1这个答案有什么遗漏吗?你只是定义了Xmodmap配置,但没有解释它是如何加载的。你提到了USB规则,所以我猜你的解决方案涉及udev魔法,但你没有描述如何配置它。 - kayahr
1啊,抱歉,在第一个代码块中找到了“Part 2”。真是让人烦恼。也许你应该将这些部分拆分成单独的代码块。否则,看起来这个代码块只是显示了你的Xmodmap文件的内容。 - kayahr
1嗯...我给你点个踩,因为你说的“现在的解决办法是关闭自动更新”。你知道吗,你可以定义自定义udev规则文件,而不是修改由xserver-xorg-core debian软件包控制的文件吗? - kayahr