initramとttyとxorgのキーマップを合わせる
もうmacOSを動かすには老朽化してしまったMacBook ProにArch Linuxを入れて遊んでます.
cf. 前回の記事
linuxのキーマップは色々設定の仕方があり,競合しないようにしたり統一するのが大変だったのでメモしておきます.
やりたいこと
- initram(LUKSの暗号化パスワード入力時)でもttyでもxorgでも,ctrlとcapslockを入れ替えたい
- ttyとxorgではctrl+gでESCを入力したい
- 昔なぜか設定したこのキーマップで慣れてしまっているので,今更変えられない.
- vimを使っているがctrl+[は両手が必要で使いづらいので,片手でタイプできてかつあまり他で使っていないctrl+gを割り当てている.
- macOSではHammerspoonで実現している.
環境
- MacBook Pro: 13-inch, 2017, Thunderbolt 3ポートx2 (A1708, MacBookPro14,1)
- Arch Linux
- Linux Kernel: 6.16.6-arch1-1
最終的な解決方法
以下のように設定することで,「やりたいこと」が実現できました.
initram
ctrlとcapslockを入れ替えるキーマップをusをベースに作成し,カスタムのHookを作ってinitramfsを作成しました. personal.map.gzはこちらで作成したものです. (FILESにカスタムしたキーマップファイルを入れるだけでそれを読んでくれるとPerplexyは言っていたのですが,それではうまく動かなかったのでカスタムHookを作成しました.)
まずはincludeされているマップを含んだフラットなキーマップファイルを作成します.
sudo loadkeys personal
dumpkeys | sudo tee /usr/local/share/kbd/keymaps/personal-flat.map次にinitram用のカスタムHookを作成します.
run_hook() {
loadkeys /usr/local/share/kbd/keymaps/personal-flat.map
}build() {
add_binary /usr/bin/loadkeys
add_file /usr/local/share/kbd/keymaps/personal-flat.map
add_runscript
}initramfsの設定におけるHOOKSにあるkeymapをmykeymapに入れ替えます.
HOOKS=(base udev modconf keyboard mykeymap autodetect microcode kms consolefont block encrypt filesystems fsck)initramfsを再作成します.
sudo mkinitcpio -Pttyとxorg
後述するように,色々試した結果,私がやりたいESCへのキーマップはrootでxremapする方法でしかできなかったので,xremapの設定を作ってサービス化しました.
まずはxremapをインストールします.
sudo paru -S xremap-x11-binctrlとcapslockの入れ替え,ctrl+gからESCのキーマップを行うxremapの設定を作成します.
modmap:
- name: swap Ctrl and CapsLock
remap:
CapsLock: Control_L
Control_L: CapsLock
keymap:
- name: remap Ctrl+G to Escape
remap:
C-g: escxremapをサービス化します.
[Unit]
Description=Xremap
After=default.target
[Service]
ExecStart=/usr/bin/xremap --watch=device /etc/xremap/config.yml
Restart=always
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.targetsudo systemctl enable xremapこれで,ログインプロンプトの時点から設定したキーマップが有効になります.
xremapはttyでも効くので(ttyでswapが2回効いてしまい戻ってしまうので),もともとカスタマイズしていた/etc/vconsle.confの設定はデフォルトに戻しました.
#KEYMAP=/usr/local/share/kbd/keymaps/personal試したけどダメだったこと
特にctrl+gをESCにマップできなくて苦労しました.
xfce4のキーボードショートカットとxdotool
xfce4のキーボード設定にあるキーボードショートカットに,ctrl+gに対するコマンドとしてxdotoolによるキー送信を設定してみましたが,ダメでした.
xdotool key Escape- ショートカットが発動したときにCtrlが押されたままの状態でEscapeが送信されることで,コンテクストポップアップメニューが開いてしまう.
xdotool keyup Control_L && xdotool key Escape && xdotool keydown Control_L- コンテキストポップアップメニューは出ないが,Escapeが入力されない.
xdotool keyup Control_L && sleep 0.01 && xdotool key Escape && sleep 0.01 && xdotool keydown Control_L- 一瞬うまくいった時があった気もするが安定しない.
- 動作後,Ctrlが押されっぱなしになったりする.
autokey-gtk
xfce4上で実行しても起動しなかったです(やり方が悪いのかも).
xkb
どうやらxkbはcontrol単独をレベル選択にはできないようで.どうやってもだめだった.
具体的にはxkbcomp $DISPLAY my.xkbとして作成したmy.xkbに対して以下のように編集をして,
type "BASE_SHIFT_CTRL" {
modifiers= Shift+Control;
map[None]= Level1;
map[Shift]= Level2;
map[Control]= Level3;
level_name[Level1]= "Base";
level_name[Level2]= "Shift";
level_name[Level3]= "Cntrol";
};
key <AC05> {
type= "BASE_SHIFT_CTRL",
symbols= [g, G ,Escape]
};それを読み込んだ後で
xkbcomp my.xkb $DISPLAYctrl+gを押した時の状況をxevコマンドで確認したところ,KeymapNotifyが表示され,マップしたつもりのESCが出力されませんでした.
これはESC以外の”G”のような印字可能なキャラクタをctrl+gにマップしても同じでした.
xorgの設定でswapとcapslockの入れ替え
これはダメだったことではないですが,xremapを導入したことで不要になったので以下の設定は削除しました.
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbOptions" "ctrl:swapcaps"
EndSectionxremapを非rootで実行する
公式のGitHubの説明に従ってやってみましたが,非rootでxremapを実行時に以下のようなエラーが出てうまく動きませんでした.
Error: Failed to prepare an output device: Permission denied (os error 13)私の環境では私しかこのマシンを使わないので,非rootでの実行は必須ではなく,rootでのサービス化をしました.