Autokeyを使ってLinuxデスクトップにMacのCommandキーみたいなものを作る

この記事は [CAMPHOR- Advent Calendar 2022](https://advent.camph.net/) 13 日目の記事です。

開発用 PC として Mac から Linux デスクトップに移行する理由は様々あると思います。例えば Docker が遅いとか Docker が遅いとか Docker が遅いとか...。  
しかし Mac から Linux に移ると Command キーがなくてビックリするのがあるあるだと思います[^1]。Mac ならターミナルだろうがそれ以外だろうが、コピペは `Command+C,V` でできるのに、Linux ではターミナル上では `CTRL+SHIFT+C,V` でそれ以外だと `CTRL+C,V` となります。Mac に慣れちゃうとこれがけっこう不便に感じるんですよね。この辺は Mac の UI の良さを実感しますね。

ところで Linux には Super キーというよくわからないものがあります[^2]。この Super キーを Command キー相当のものに改造するために、僕は Autokey というソフトウェアを利用しています。

## Autokey
[Autokey](https://github.com/autokey/autokey) は Linux デスクトップにおいて、特定のキーが押されたときの動作を変更することができるものです。そして、その変更された動作を Python スクリプトで記述することができるのが特徴です。

## Install

Arch 系のディストロでは [AUR](https://aur.archlinux.org/pkgbase/autokey) で配布されています。Ubuntu でも apt でインストールできるようです。

## 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953258/2b4ab67e-0a5f-d924-e2b6-a09bfbed58aa.png)


Autokey を起動すると上のような GUI が開かれます。左側に作成されたスクリプトの一覧が表示されます。New ボタンを押すと新たにスクリプトを作成することができます。そして右側に開かれているのが僕の `Command+C` に相当するスクリプトです。ちょっと解説してみます。

### スクリプトの記述

```python:command-c.p
from helper import is_terminal

key = 'c'

c = window.get_active_class()
if is_terminal(c):
    keyboard.send_keys('<ctrl>+<shift>+' + key)
else:
    keyboard.send_keys('<ctrl>+' + key)
```

Autokey からは `window` とか `keyboard` とかいう API が提供されています[^3]。これを利用してデスクトップの情報やキー入出力の情報をやりとりできます。

1 行目は自分で作成したヘルパー関数を import しています。(後述)
5 行目は、現在アクティブになっている window の種類を取得しています。種類というのはおそらくアプリごとに設定されているようです。例えば Firefox のウィンドウ、VSCode のウィンドウ、といった具合です。  
6 行目は、取得されたウィンドウの種類がターミナルであるかどうかを判断しています。この分岐によって、`CTRL+SHIFT+C` と `CTRL+C` を出し分けています。こうすることで、ターミナルであろうがそれ以外であろうが、`SUPER+C` はコピーのショートカットになります。

さて、先述したとおり、Autokey は自分で作成したヘルパー関数を import するということもできます。ヘルパー関数の定義は以下のとおりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953258/a41d7061-3f54-9091-d8eb-3f50ef68dd56.png)

```python:helper.py
terminals = [\
    'xfce4-terminal.Xfce4-terminal', \
    'tilix.Tilix', \
]

def is_terminal(c):
    for t in terminals:
        if t == c:
            return True
    return False
```

関数 `is_terminal` で、そのウィンドウがターミナルウィンドウの種類のいずれかであるかどうかというのを返しています。ターミナルのウィンドウの種類の一覧が `terminals` でハードコーディングされています。

このようにヘルパー関数で切り出しておけば、他のキーで設定するときに楽ができます。

### ウィンドウクラスの取得

じゃあこのターミナルのウィンドウの種類 (正確にはクラス？) はどこで知ったのかというと、GUI の右下に `Window Filter` という箇所がありますね。この `Set` ボタンを押してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953258/2cd8db4f-beb7-725b-8f3e-221cc17b0c47.png)

このようなモーダルが表示されるので、`Detect Window Properties` というボタンを押したあと、例えば Firefox というウィンドウをクリックすると、Firefox のウィンドウクラスが取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953258/3639d417-2be6-c31e-cc98-3aa59f9b7aeb.png)

### Hotkey の設定

記述したスクリプトを `SUPER+C` を押したときに起動するように設定すれば完了です。この設定はGUI 右下の Hotkey という箇所でできます。

## Autokey のイマイチなところ

- たまにスクリプトの起動が遅い
  - なぜかそのせいで `COMMAND+V` を押したときに `v<copied_text>` みたいになることがある
- VSCode のターミナルで同じことができない。なぜならウィンドウクラスごとに処理を分岐しているから (ウィンドウの中のこの部分という分岐のさせ方はできないっぽい。できたら教えてください。)


[^1]: Mac から Windows に移るときも同様
[^2]: 本来の Super キーは押すことでアクティビティを開くことができるようです。Window キーと同じですね。僕のデスクトップ環境は [Mac-like に魔改造](https://www.youtube.com/watch?v=uvvoJU69uNo&t=2180s)されているので使いみちはなさそうです。「本来の Super キーめっちゃ便利だよ」っていうのがあれば教えてください。
[^3]: [API ドキュメント](https://autokey.github.io/index.html)もあるが、[サンプルスクリプト集](https://github.com/autokey/autokey/wiki/Example-Scripts)を眺める方が手っ取り早い。