7
31
2015
10

交换 ThinkPad 键盘上的 Insert 和 End 键

本文来自依云's Blog,转载请注明。

ThinkPad 键盘上的第一行键现在默认在不按下Fn键时执行多媒体按键功能,按下Fn时才能执行F1-F12的功能,对于像我这种 Vimhtop 等的用户来说颇为不便。还好,BIOS 选项里可以改回来。

然后我遇到了 X250,发现InsertEnd键怎么也受那个选项的影响了!也就是,如果F1-F12设置得方便了,那么End键就需要Fn键配合。而HomeEnd这种光标移动键虽然很少用,但毕竟还是要用到的,比如在 htop、weechat、mutt 以及不支持自定义编辑键的 Qt 程序里的时候。

所以呢,我在~/.Xmodmap里把这两个键交换了:

keysym End = Insert
keysym Insert = End

这下子用笔记本上的键盘是没问题了。可是我用外接键盘的话,这两个键就又反过来了 Orz……

当然网上会有 udev 规则,在插上外设时跑个脚本什么的。可不管怎么映射,总有个键盘的按键是反的啊

仔细询问 Google 之后,在 Gentoo 的论坛里终于发现这么一条线索

To alter keymap of a particular keyboard you need to issue EVIOCSKEYCODE ioctl on corresponding /dev/input/eventX node.

所以,找到相应的 event 设备文件之后,只需要 ioctl 一下就可以了?可是EVIOCSKEYCODE是个什么鬼啊……

找过 manpages、头文件、内核文档、Google 之后,我不得不相信这个东西真的没文档!于是只好看源码了……还好有 LXR,不用在本地近一个G的源码里搜索。

所以,翻完文档又试验,最终有了这个程序:

#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<linux/input.h>

#define EVENT_FILE "/dev/input/by-path/platform-i8042-serio-0-event-kbd"

int main(int argc, char **argv){
  unsigned int codes[][2] = {
    {0xd2, 107}, //Insert -> End
    {0xcf, 110}, //End -> Insert
    {0, 0},
  };
  int fd = open(EVENT_FILE, O_RDONLY);
  if(fd < 0) {
    perror("open " EVENT_FILE);
    exit(1);
  }

  unsigned int (*p)[2];
  for(p=codes; *p[0]; p++){
    if(ioctl(fd, EVIOCSKEYCODE, *p)) {
      perror("ioctl EVIOCSKEYCODE");
      exit(1);
    }
  }
  return 0;
}

那个EVENT_FILE当然就是笔记本键盘的节点啦,在/dev/input/by-path下很容易识别的。

编译之后,每次启动系统后执行一次就可以了(大概)。

对了,顺便说一下,找那些代码可以用 showkey 和 getkeycodes 之类的命令。当然我们有 setkeycodes,但是它不能为指定键盘单独设置。传进去的参数,第一个整数是 scancode,就是硬件上报的编码,第二个是 keycode,内核给键的编码,不同硬件的不同 scancode 可以对应同一个 keycode(比如本文所做的)。然后文本终端还有 keymap、X Window 还有键盘布局和 xmodmap,大概是把 keycode 映射到可读的键名。

Category: Linux | Tags: linux C代码 外部设备 输入设备 | Read Count: 19399
ppwwyyxx 说:
Aug 02, 2015 10:25:16 AM

udev规则里可以改一个usb设备的mapping
似乎叫hwdb还是什么…

Avatar_small
依云 说:
Aug 02, 2015 12:47:17 PM

关键问题是怎么改一个设备的键映射,而不是怎么触发。hwdb 跟键盘没关系呀。

ppwwyyxx 说:
Aug 02, 2015 03:12:20 PM

udev不光是用来触发的. hwdb里是可以写一个scancode到keycode的mapping, mapping仅对一个设备生效

Avatar_small
依云 说:
Aug 02, 2015 04:15:34 PM

原来如此,找到了~ https://wiki.archlinux.org/index.php/Map_scancodes_to_keycodes

wzyboy 说:
Aug 06, 2015 04:40:29 PM

我在 X240s 上也遇到了这个问题,当时是

keycode 118 = End NoSymbol End
keycode 115 = Insert NoSymbol Insert

这样解决的……

后来接了外接键盘之后就不管了(

f 说:
Sep 06, 2015 08:46:14 AM

所以还是老版的键盘好…

@xuboying 说:
Nov 27, 2015 05:06:57 PM

老版本的Thinkpad非常好用.不过绝对的vim党不是应该用hhkb么

wzyboy 说:
Nov 27, 2015 05:08:23 PM

是啊,我外接的就是 HHKB Pro2 Type-S

Avatar_small
依云 说:
Nov 27, 2015 06:22:06 PM

我觉得 HHKB 是给 Emacser 设计的啊。

f 说:
Nov 28, 2015 10:00:41 PM

HHKB那键位,方便 Ctrl 的触发,怎么看都是给 Emacs 用户设计的……
Vim 没那么挑键盘,尤其是用久了后好多人都不用 Esc 来切换状态。

不过我还是喜欢87键这种,喜欢老版 Thinkpad 的键盘一样,因为Insert Delete Home End 很顺手,不管是用什么编辑器或者什么软件的时候,有的用还是方便。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com