LinuxでKeymapをmacOSぽくする

  #linux

macユーザがmacOS離れをすると、キーマップ問題にだいたい悩まされる。
みんな同じ悩みを抱えている様子だけど、ベストプラクティスらしいものは見つからない。

自分もその1人だけど、今回だいぶ満足できる環境になったのでメモしておく。

macOSぽいキーマップとは

macOSではcommandctrlで役割がちゃんと分離されている。
commandキーを使ったショートカットは、全て選択・カット・ペースト・ウィンドウを閉じる、といったよくある操作が設定されている。一方ctrlキーを使ったショートカットは、行の先頭/末尾に移動する・行を移動する、といったemacsライクな操作が設定されている。この住み分けが非常に使いやすく、矢印キーまで手を伸ばす必要がなくホームポジションを維持しやすい。

macOSのキーマップに慣れてしまうと、他OSで文章入力中にC-aとかC-nを打ったときのストレスが地味に蓄積する。慣れてしまえばOS毎にショートカットは使い分けできるが、文章入力に関してはどうしてもカーソル移動に不便を感じてしまう。それくらいにmacOSのキーマップは素晴らしく、一度経験すると他OSのキーマップに不満を感じてしまうほどに依存性が高い。

環境

ハードウェアはThinkPad X1 Carbon 2017。
Ubuntu 18.04でデスクトップ環境はGnomeを使っている。
使用しているアプリケーションでキーマップの検討に関わるものは以下。

このあたりかな。

目指すキーマップ

デフォルトの状態はこんな感じ。
ちなみにwinキーはsuperキーとして扱われる(厳密にはこの言い方は正しくないんだろうけど簡単のため)。

[tab]
[caps]
[shift]
[fn][ctrl][super][alt][space][alt]

これを以下の様にする。

[tab]
[ctrl]
[shift]
[fn][caps][meta][alt][space][alt]

ただし、JetBrains系ツールではleft_altleft_metaをswapさせる。

[tab]
[ctrl]
[shift]
[fn][caps][alt][meta][space][alt]

JetBrainsユーザ向けのポイントとしては

の2点。

JetBrainsツールのキーマップに"Mac OS X"という設定があり、これがmetaを中心に構成されている。いちいち自分でキーマップ設定を作るよりも、既存の設定を使いまわせるほうがお手軽なのでこんなことをしている。
JetBrainsユーザではない場合は、この辺考えなくていいのでもっと楽に設定できると思う。

設定

やることざっくり書くと。

xkeysnailで頑張るスタイル。

dconf

supermetaにする。gsettingsコマンドでもgnome tweaksでも好きな方で。

$ gsettings set org.gnome.desktop.input-sources xkb-options "['altwin:meta_win']"

gnome tweaksの場合、“Meta is mapped to Win"というのが、altwin(meta_win)に対応している。

自分の環境ではこんな感じになる。

$ setxkbmap -print
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+us+us:2+inet(evdev)+altwin(meta_win)"	};
	xkb_geometry  { include "pc(pc105)"	};
};

dconf(xkb)側ではctrlcapsのswapは設定しない。xkeysnailを使う場合、そちらでswapの設定を入れないと意図したキーマップにならないため。

次に、アプリケーション切り替えのキーマップを追加する。
これはJetBrainsツール使用時のみaltmetaになっているため。meta+tabでもアプリケーションを切り替えられるようにする。

$ gsettings get org.gnome.desktop.wm.keybindings switch-applications
['<Alt>Tab']
$ gsettings set org.gnome.desktop.wm.keybindings switch-applications "['<Alt>Tab', '<Super>Tab']"

$ gsettings get org.gnome.desktop.wm.keybindings switch-applications-backward
['<Shift><Alt>Tab']
$ gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "['<Shift><Alt>Tab', '<Shift><Super>Tab']"

xkeysnail

あんまりよくないけど、sudoで入れちゃう。

$ suso pip3 install xkeysnail

ちゃんとするならxkeysnailユーザ作った後にそのユーザスペースにインストールする方がお行儀良いかな。

設定はこちらを参照。

https://github.com/kobtea/dotfiles/blob/c2ae3342f2e895b75bb8d9b8db0bc7e6dd4a89fe/xkeysnail.py

ctrlcapsをswapしたり、アプリケーションごとにキーマップを設定している。あんまりスマートではないけど、漏れがあったら随時追加していくスタイル。ちなみにFocusProxyというのがJetBrainsツール。

rootで実行は避けたいので、専用ユーザを作成する。
参考: xkeysnailでキーリマップする - Qiita

$ sudo groupadd uinput
$ sudo useradd -G input,uinput -M -s /usr/bin/nologin xkeysnail
$ cat /etc/udev/rules.d/40-udev-xkeysnail.rules
KERNEL=="uinput", GROUP="uinput"
$ cat /etc/modules-load.d/uinput.conf
uinput

起動スクリプトを準備して、gnome startup applicationsに登録する。

https://github.com/kobtea/dotfiles/blob/c2ae3342f2e895b75bb8d9b8db0bc7e6dd4a89fe/xkeysnail.sh

JetBrains Tools

各ツールのKeymapで"Mac OS X"を選択するだけ。

おわりに

今回の設定で自分は満足する環境を手に入れたけど、まぁ面倒くさいこと。macOSのキーマップを完全に再現できるのは結局の所macOSだけなので、ハードウェアに不満がなければMacBook買えばいいと思う。自分はペチペチキーボードがどうにも合わないので、当分ThinkPadとUbuntuにお世話になるつもり。

余談: xkbを諦めた話

xkeysnailを使う前はxkbでなんとかできないかなーと試行錯誤していたけど結局無理だった。
そんな挫折ポイントを2つほど書き残しておく。

キーマップの変更が非推奨

参考: X KeyBoard extension - ArchWiki

xkbの設定には2種類ある。

悲しいことにaltwin(meta_win)などのsymbolを自分で定義する方法は、非推奨なキーマップ編集でのみ可能。そして、そのキーマップは/usr/share/X11/xkb/のみを参照し、$HOME/.xkbといったユーザ固有のパスは提供されていない。symbolをカスタマイズする場合は、強い気持ちで/usr/share/X11/xkbを編集していく必要がある。

Fcitxが設定をロールバックする

自分は/usr以下をいじりたくなかったので、自前の設定とそれを読み込む以下のスクリプトを作成し、gnome startup applicationsに登録した。

#!/bin/sh
sleep 10
test -f $HOME/.xkb/keymap/mykbd.xkb && xkbcomp -I$HOME/.xkb $HOME/.xkb/keymap/mykbd.xkb $DISPLAY 2> /dev/null

これで任意のsymbolを適用できるようにはなったが、Fcitxのキー設定を変更すると/usrで定義されたデフォルトの状態へとロールバックされてしまう。

ここでxkbは挫折した。もっと柔軟に設定できると嬉しいなー。