Linux (Ubuntu 24.02) でキーボードリマッピング
Ubuntuを使いやすくするために
最近新卒で入った会社の社用ノートPC(Ubuntu)を使いやすく(Macっぽく)するために調べたので共有します。具体的には以下を設定しました。
-
Cmd⌘
キーの実装
Ubuntuでは同じショートカットCtrl
+C
がターミナルでは強制終了、その他のアプリケーションではコピーに割り振られているので、アプリによって使うショートカットが変わって不便です。MacではCtrl⌃
キーの他に、Cmd⌘
キーがありCtrl⌃
+C
で強制終了、Cmd⌘
+C
でコピーとどのアプリケーションでも同じように動作するのでこれを設定します。 -
CapsLockキーのリマッピング
個人的にあまり使い道のないCapsLock
キーが左手の押しやすいところにあるので、それを別のキー(今回はMacでいうCtrl⌃
キー)を割り振ります。 -
UK/USキーボードの変換
イギリスの会社なので渡されたノートのキーボードはUK配列で、リモートワーク用に買った自宅用キーボードのがUS配列なのでこれを自動的に識別して変換します。
Toshy: Make your Linux keyboard act like a 'Tosh!
他のLinuxディストリビューションではxkeysnailやKintoといったいくつかのキーマッピングツールがあるのですが、これらはUbuntu 21.04以降でデフォルトのウィンドウシステムWaylandに対応しておらず [1] 困っていました。そんな中、ToshyはWaylandに対応していて、かつ、とても使いやすかったです。
基本はPythonで書かれていて、Ubuntuを始め、CentoOSやDebianなど幅広いディストリビューションに対応しています(動作確認済みのOSのリストはこちら)
インストール手順
Toshy本体のインストール
リポジトリの指示に従うだけです。Python 3.8以上が入っているならDependencyも含めてすべてインストールされると思います。
git clone https://github.com/RedBearAK/toshy.git
cd toshy
./setup_toshy.py install # 途中でroot権限を要求されます
個人的に好感が持てたのはこのインストールでSystemのPythonには何もインストールしない という点です。[2] そのため、アンインストールも簡単です。
./setup_toshy.py uninstall
Wayland + GNOMEのためのプラグインインストール
UbuntuのデフォルトのDesktop System (GNOME
) を使っていると追加のツールが必要です。これらはFlatHubで公開されているものを使います
1. FlatPak (FlatHub用のパッケージマネジャー) のインストール
sudo apt install flatpak
sudo apt install gnome-software-plugin-flatpak
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
FlatPakインストール後再起動が必要です。
2. (Optional) Extension Managerのインストール
flatpak install extensionmanager
これを使うとGUIでパッケージがインストールできて便利です。
3. 以下のいずれかのパッケージをインストール
-
'Xremap' (Supports GNOME 3.36/3.38, and 40 or later)
- UUID: xremap@k0kubun.com
- URL: https://extensions.gnome.org/extension/5060/xremap/
-
'Window Calls Extended' (Supports GNOME 41 or later)
- UUID: window-calls-extended@hseliger.eu
- URL: https://extensions.gnome.org/extension/4974/window-calls-extended/
-
'Focused Window D-Bus' (Supports GNOME 43 or later)
- UUID: focused-window-dbus@flexagoon.com
- URL: https://extensions.gnome.org/extension/5592/focused-window-d-bus/
あまりバージョンとか気にせずに、複数入れても問題ないそうです。
There is no risk of any kind of conflict when installing more than one of the compatible shell extensions. Which might be advisable, to reduce the risk of not having a working extension for a while the next time you upgrade your system in-place and wind up with a newer version of GNOME that one or two of the extensions hasn't been updated to support. I expect at least one of the (now three) extensions will always be updated quickly to support the latest GNOME.
できた!
インストールが成功するとUbuntu TrayにToshyアイコン(一番左のスラックみたいなアイコン)がでます。
これに色がついているとToshyが無事に動いています。ToshyはUbuntuをMacのショートカットのように動かすための最低限の設定があらかじめ入っており、これで目的の1つ目「Cmd⌘
キーの実装」がほぼ自動的に達成されます。 詳しくは後で説明するのですが、スペースキーの一つ左のボタン がMacでいうところの Cmd⌘
キー として動くようになり、どのアプリケーションでもコピーやペーストが同じショートカットで動きます。
また、よく使うことになる設定「 Capslock
キーをCmd⌘
キー にマップする」や「NumsLockを自動的にOnにする」もToshy アイコンをクリックしてでてくるPreferenceから設定できます!これでUbuntuをMacintosh-yに操れます
さらなるカスタマイズ
Toshyの魅力は設定がPythonで書かれていて、自分で自由に変更が可能なところです。Toshyのキーマッピングはxwaykeyzというパッケージに依存しており、~/.config/toshy/toshi_config.py
がそのための設定となっています。(気になる人のために下のアコーディオンにに主要な関数のDocumentを乗せておきます。)
xwaykeyzの詳細
カスタマイズをする際には主に modmap
関数とkeymap
関数を追加することになります。
これらの定義は依存パッケージのに書いてあります
modmap(name, mappings, when = None)
修飾キー(Ctrlなど) を別の修飾キーにマッピングします
-
name:str
マッピングの名前。デバッグ用。 -
mappings:dict[Key, Key]
修飾キーの変換前と変換後のdict
-
when_conditional: Callable[KeyContext, bool]
変換を行う条件を指定する。
具体例:
modmap("Cond modmap - GUI - Win kbd", {
# ...
Key.LEFT_ALT: Key.RIGHT_CTRL, # WinMac
}, when = lambda ctx:
isKBtype('Windows', map='mmap GUI Win')(ctx) and
matchProps(not_clas=terms_and_remotes_Str)(ctx)
)
ここでは、左の Alt
キーが右の CTRL
キーにマッピングされています。これが有効となるのは windowsタイプのキーボード (isKbType("Windows")
)かつ、アクティブなウィンドウがターミナルやリモートデスクトップクライアントでない (matchProps(not_clas=terms_and_remotes_Str)
)ときです。それぞれの条件についてはdefault config ~/.config/toshy/default-toshy-configh/toshi_config.py
に関数の定義が書いてあります。
keymap(name, mappings, when = None)
あるキー(の組み合わせ)が入力されたとき、それを別のキー(の組み合わせ)に変換して出力します。
-
name:str
マッピングの名前。デバッグ用。 -
mapptings:dict
{combo: command}
で変換を指定します。-
combo
:C(combo_str)
で入力キーの組み合わせを指定します。詳しくはCombo Specificationのページを参照します。 -
command
: 以下のいずれかを指定します。-
C(combo_str)
: 出力キーの組み合わせ -
List[command]
: 複数のコマンドが次々に出力されます -
{combo: ...}
: 複数キーストロークでのショートカット(e.g.C_x
+C_c
をC-q
にする) - 特殊なキーワード
-
"bind"
: 入力の修飾キーが押されている間出力の修飾キーも押下された状態にする -
iEF2NT()
:Enter
キーが押されたらエスケープする
-
-
-
下に記事の最初の目的を達成するために自分が使っている設定を載せます。自前の設定を書く場所は~/.config/toshy/toshi_config.py
にいくつかある
###################################################################################################
### SLICE_MARK_START: ほげほげ ### EDITS OUTSIDE THESE MARKS WILL BE LOST ON UPGRADE
### SLICE_MARK_END: ほげほげ ### EDITS OUTSIDE THESE MARKS WILL BE LOST ON UPGRADE
###################################################################################################
の 間 です。ほげほげ
にはどういった種類のカスタム設定を書くべきか指定されているのですが多分深く考えなくても大丈夫です(試してはいません)
CapsLockキー
をCtrl⌃
キーに設定する
Toshyアイコンをクリックして出てくる設定では Capslock
キーをCmd⌘
キー にマップする事はできても、Ctrl⌃
キー に設定することはできません。これをするためには以下をconfigに追加します。
# Set CapsLock as Ctrl in Mac rather than Cmd
modmap("User Cond modmap - Caps2CTRL", {
Key.CAPSLOCK: Key.LEFT_CTRL # Caps2Ctrl
}, when = lambda ctx:
isKBtype('Windows')(ctx) and matchProps(not_clas=remoteStr)(ctx)
)
ここでKey.LEFT_CTRL
を指定することが大事で、Key.RIGHT_CTRL
を設定するとMacでの**Cmd⌘
キー** に対応する修飾キーとなってしまいます。また余計な誤作動を防ぐためにTweaksでCapsLockをdisableしておくと安心です。
入力ソースの切り替えを設定する
Macのデフォルトでは入力ソースの切り替えは Ctrl⌃
+ Space
ですが、Ubuntuだと Super
+ Space
なのでこれを設定します。
keymap("User overrides input source change", {
C("LC-Space"): [iEF2NT(),bind, C("Super-Space")],
C("Shift-LC-Space"): [iEF2NT(),bind, C("Shift-Super-Space")],
}, when = lambda ctx:
cnfg.screen_has_focus
and matchProps(not_clas=remoteStr)(ctx)
and isKBtype('Windows')(ctx)
)
ここで、bind
を設定することで Ctrl⌃
を押している間、選択ウィンドウが消えなくなるようにすることができます。
UKキーボードに対応する
US配列とUK配列で場所が異なっている部分をToshy上で補正することで、UK配列のキーボードを接続しても English(US)の入力ソースのまま入力ができます。
UK_layout_keyboard = ["UK配列キーボードの名前1", "UK配列キーボードの名前2",...]
keymap("User hardware keys", {
C("Shift-2") : C("Shift-Apostrophe"), # Double quotation
C("Shift-Apostrophe") : C("Shift-2"), # @ symbol
C("Backslash"): C("Shift-3"), # # symbol
C("Shift-Backslash"): C("Shift-Grave"), # ~ symbol
C("Shift-3"): UC(0x00A3), # £ symbol
C("KEY_102ND"): C("Backslash"), # \ symbol
C("Shift-KEY_102ND"): C("Shift-Backslash"), # | symbol
}, when = lambda ctx:
cnfg.screen_has_focus and
any((matchProps(devn=name)(ctx) for name in UK_layout_keyboard))
)
キーボードの名前の取得方法ですが、ターミナルで
toshy-debug
と入力し、設定したいキーボードでキーを入力すると、
(DD) WM_CLASS: 'Xfce4-terminal' | WM_NAME: 'Terminal - testuser@mx: ~'
(DD) DEVICE: 'AT Translated Set 2 keyboard' | CAPS_LOCK: 'False' | NUM_LOCK: 'False'
(DD) ACTIVE KEYMAPS:
'User hardware keys', 'Wordwise - not vscode', 'GenTerms overrides: Xfce4',
'General Terminals', 'GenGUI overrides: not Chromebook', 'GenGUI overrides:
… Xfce4', 'General GUI'
(DD) COMBO: RCtrl-MINUS => Ctrl-MINUS in KMAP: 'General Terminals'
....
などのようなログが出ます。ここでDEVICE
のあとの文字列がキーボードの名前です。(この例だと 'AT Translated Set 2 keyboard' )です。
-
以前のウィンドウシステムX11で、そのウィンドウがどのアプリケーションで開かれているかを管理する
WM_CLASS
プロパティが、Waylandだと設定されないことがある、というのが原因みたいです。詳しい話は詳しい人に聞いてください↩︎ -
以前にKintoも試したのですが、システムのPythonに(勝手に)依存パッケージをインストールして、Kintoのアンインストールをしてもそれが残り続けました。しかし、Toshyは
~/.local/bin/
下に仮想環境を作りそこに依存をインストールするため、--break-system-packages
などのシステムを破壊する可能性のあることをしなくてもインストール、アンインストールが簡単です。また、インストール時のPythonもシステムではなく、pyenv
でインストールしたものを使用することも可能です。 ↩︎
Discussion