j3iiifn’s blog

ネットワーク、インフラ、プログラミングについての備忘録

Karabiner-ElementsでSandS設定時にIME切り替え(control+space)が遅延する問題と解決方法

前提条件

この記事は、以下の条件に該当する人向けの内容である。

  • macOSを使用している
  • Karabiner-Elements v15.0.0以降を使用している
  • IME切り替えにcontrol + spaceを使用している(macOSのデフォルト設定)
  • Karabiner-ElementsでSandS(Space and Shift)を設定している

SandS(Space and Shift)とは

SandSとは、spaceキーに2つの役割を持たせるキーマッピング手法である。

  • spaceキーを単独で押して離す → 通常のspace入力
  • spaceキーを押しながら他のキーを押す → Shiftキーとして機能

Karabiner-Elementsでは、以下のような設定で実現できる。

{
    "description": "Change spacebar to left_shift. (Post spacebar if pressed alone)",
    "manipulators": [
        {
            "from": {
                "key_code": "spacebar",
                "modifiers": { "optional": ["any"] }
            },
            "to": [{ "key_code": "left_shift" }],
            "to_if_alone": [{ "key_code": "spacebar" }],
            "type": "basic"
        }
    ]
}

この設定は事前定義済みであるため、以下の手順でマウスクリックするだけで設定可能である。

  1. Karabiner-Elementsを起動する
  2. 左側のメニューで [Complex Modifications] をクリックする
  3. [Add predefined rule] ボタンをクリックする
  4. [Change spacebar to left_shift. (Post spacebar if pressed alone)] の右側にある [Enable] ボタンをクリックする

Karabiner-Elementsのpredefined rule

事象

上記のSandS設定を使用している状態でcontrol + spaceを押してIMEを切り替えると、以下の問題が発生する。

  • IME切り替えに遅延が発生する
  • 1文字目の入力が意図と反対のIMEで行われてしまう

原因

SandSの設定では、spaceキーを押した瞬間にleft_shiftが送信される。そのため、control + spaceを押すとcontrol + left_shiftとして処理されてしまい、IME切り替えのショートカットが正常に認識されない。

Ctrlを長押ししながらSpaceを押下したときのKarabiner-EventViewer

解決方法

control + spacebarの組み合わせをSandS変換の対象から除外するルールを追加する。

{
    "description": "Change spacebar to left_shift. (Post spacebar if pressed alone, pass through with control)",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "spacebar",
                "modifiers": {
                    "mandatory": ["control"],
                    "optional": ["caps_lock"]
                }
            },
            "to": [
                {
                    "key_code": "spacebar",
                    "modifiers": ["control"]
                }
            ]
        },
        {
            "from": {
                "key_code": "spacebar",
                "modifiers": { "optional": ["any"] }
            },
            "to": [{ "key_code": "left_shift" }],
            "to_if_alone": [{ "key_code": "spacebar" }],
            "type": "basic"
        }
    ]
}

ポイント

  1. 最初のルールがcontrol + spacebarを検出し、そのままcontrol + spacebarを送信する(SandS変換をバイパス)
  2. 2番目のルールは既存のSandS設定で、control以外の場合にShift変換を行う
  3. Karabiner-Elementsはルールを上から順に評価するため、control + spaceのルールを先に配置する必要がある

補足:他のモディファイアキーも除外したい場合

command + spaceなど他の組み合わせも除外したい場合は、以下のように追加できる。

{
    "description": "Change spacebar to left_shift. (Post spacebar if pressed alone, pass through with modifiers)",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "spacebar",
                "modifiers": {
                    "mandatory": ["control"],
                    "optional": ["caps_lock"]
                }
            },
            "to": [{ "key_code": "spacebar", "modifiers": ["control"] }]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "spacebar",
                "modifiers": {
                    "mandatory": ["command"],
                    "optional": ["caps_lock"]
                }
            },
            "to": [{ "key_code": "spacebar", "modifiers": ["command"] }]
        },
        {
            "from": {
                "key_code": "spacebar",
                "modifiers": { "optional": ["any"] }
            },
            "to": [{ "key_code": "left_shift" }],
            "to_if_alone": [{ "key_code": "spacebar" }],
            "type": "basic"
        }
    ]
}

参考