⌨️

Linux (Ubuntu 24.02) でキーボードリマッピング

2024/09/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ディストリビューションではxkeysnailKintoといったいくつかのキーマッピングツールがあるのですが、これらはUbuntu 21.04以降でデフォルトのウィンドウシステムWaylandに対応しておらず [1] 困っていました。そんな中、ToshyはWaylandに対応していて、かつ、とても使いやすかったです。

https://github.com/RedBearAK/toshy

基本は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. 以下のいずれかのパッケージをインストール

あまりバージョンとか気にせずに、複数入れても問題ないそうです。

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] 変換を行う条件を指定する。

具体例:

~/.config/toshy/toshi_config.py
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_cC-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' )です。

脚注
  1. 以前のウィンドウシステムX11で、そのウィンドウがどのアプリケーションで開かれているかを管理するWM_CLASSプロパティが、Waylandだと設定されないことがある、というのが原因みたいです。 詳しい話は詳しい人に聞いてください ↩︎

  2. 以前にKintoも試したのですが、システムのPythonに(勝手に)依存パッケージをインストールして、Kintoのアンインストールをしてもそれが残り続けました。しかし、Toshyは ~/.local/bin/下に仮想環境を作りそこに依存をインストールするため、--break-system-packagesなどのシステムを破壊する可能性のあることをしなくてもインストール、アンインストールが簡単です。また、インストール時のPythonもシステムではなく、pyenvでインストールしたものを使用することも可能です。 ↩︎

Discussion