Karabiner-Elementsで右Command単押しを「かな」にしたら入力済み文字が消えた話

OpenTech

Macで日本語入力を快適にするため、Karabiner-Elementsを使って次のような設定にしていました。

ところが、右Commandを押したときに、すでに入力していた文字の末尾が変換されたり、入力済みの文字列が消えたように見えたりする問題が発生しました。この記事では、元の設定と、問題を改善できた設定の違いを紹介します。

元の設定

最初は、左右のCommandキーを単押ししたときに、それぞれ japanese_eisuujapanese_kana を送る設定にしていました。

{
  "description": "コマンドキーを単体で押したときに、英数・かなキーを送信する。(左コマンドキーは英数、右コマンドキーはかな) (rev 3)",
  "manipulators": [
    {
      "from": { "key_code": "left_command", "modifiers": { "optional": ["any"] } },
      "parameters": { "basic.to_if_held_down_threshold_milliseconds": 100 },
      "to": [{ "key_code": "left_command", "lazy": true }],
      "to_if_alone": [{ "key_code": "japanese_eisuu" }],
      "to_if_held_down": [{ "key_code": "left_command" }],
      "type": "basic"
    },
    {
      "from": { "key_code": "right_command", "modifiers": { "optional": ["any"] } },
      "parameters": { "basic.to_if_held_down_threshold_milliseconds": 100 },
      "to": [{ "key_code": "right_command", "lazy": true }],
      "to_if_alone": [{ "key_code": "japanese_kana" }],
      "to_if_held_down": [{ "key_code": "right_command" }],
      "type": "basic"
    }
  ]
}

この設定では、現在の入力モードに関係なく、右Commandを単押しするたびに japanese_kana が送信されます。IMEやアプリ、そのときの入力状態によっては、このイベントが既存文字列に対する変換や再変換のような動作として扱われます。

改善方法

対策として、現在の入力ソースを確認する条件を追加しました。すでに日本語入力なら右Commandで japanese_kana を送らず、すでに英数入力なら左Commandで japanese_eisuu を送りません。

{
  "description": "Command単押しで英数・かな(現在の入力ソースを判定)",
  "manipulators": [
    {
      "type": "basic",
      "from": { "key_code": "left_command", "modifiers": { "optional": ["any"] } },
      "to": [{ "key_code": "left_command", "lazy": true }],
      "to_if_alone": [{ "key_code": "japanese_eisuu" }],
      "to_if_held_down": [{ "key_code": "left_command" }],
      "conditions": [{ "type": "input_source_if", "input_sources": [{ "language": "^ja$" }] }],
      "parameters": {
        "basic.to_if_alone_timeout_milliseconds": 250,
        "basic.to_if_held_down_threshold_milliseconds": 150
      }
    },
    {
      "type": "basic",
      "from": { "key_code": "right_command", "modifiers": { "optional": ["any"] } },
      "to": [{ "key_code": "right_command", "lazy": true }],
      "to_if_alone": [{ "key_code": "japanese_kana" }],
      "to_if_held_down": [{ "key_code": "right_command" }],
      "conditions": [{ "type": "input_source_unless", "input_sources": [{ "language": "^ja$" }] }],
      "parameters": {
        "basic.to_if_alone_timeout_milliseconds": 250,
        "basic.to_if_held_down_threshold_milliseconds": 150
      }
    }
  ]
}

右Commandに入力ソースの条件を追加

input_source_unless は、指定した入力ソースではない場合にだけルールを適用する条件です。現在の入力言語が日本語ではない場合だけ、右Command単押しで japanese_kana を送ります。

左Commandにも反対の条件を追加

input_source_if は、指定した入力ソースの場合にだけルールを適用する条件です。現在の入力言語が日本語の場合だけ、左Command単押しで japanese_eisuu を送ります。

単押しと長押しの判定時間を調整

元の100ミリ秒から、単押しのタイムアウトを250ミリ秒、長押しの判定を150ミリ秒へ変更しました。単押しとCommandショートカットの判定が安定しやすくなります。入力済み文字が消える問題に直接効果があったのは、判定時間よりも conditions の追加です。

まとめ

問題は、現在の入力モードに関係なくCommandキーを単押しするたびに英数キーやかなキーを送っていたことで発生していました。Karabiner-Elementsの入力ソース条件を使い、切り替えが必要な場合にだけイベントを送ることで改善しました。