アフィリエイト広告を利用しています

Screens 5 で英数/かなキーが効かない【Karabiner】画面共有のIME同期を Hammerspoon 中継で復活させる

以前、画面共有中に英数/かなキー1発で、ローカルとリモートのIMEを同時に揃える Karabiner-Elements の設定をClaude Codeを使って記事にしました。

(元記事へのリンク: 画面共有のIME切り替え【Karabiner-Elements】英数/かなキー1発でローカルとリモートを同時に揃える)

その後、画面共有アプリを Apple 標準の「画面共有.app」から Screens 5 に乗り換えた。

そうしたら、この仕組みが動かなくなりまして。

英数キー、かなキーを押しても、ローカルだけ切り替わって、リモートは反応しないんですよね。

Claude CodeのFable5で色々と試して、わかったのが、原因は2つ。

Screens 5(VNCベース)は、英数/かなキーをリモートまで運ばない様子。そして、リモート側では「セキュア入力」が F18 などの通常キーを握りつぶしていたこと。

最終的に「英数 = fn+左Control、かな = fn+左Option」という修飾キーの組み合わせを送り、リモート側は Hammerspoon で受ける方式にしたらバッチリでした。

1つのキー操作で両方のIMEがバチッと揃う。快適です。(iPadでのリモートアクセスだと、これができないので、Macからやるのが良いんだろうな、そうなると、MacBookNeo がリモートアクセスのマシンとして最高な気がしています)

bundle ID を足すだけでは動かなかった

最初は簡単に終わると思っていた。詳細はClaude Codeに任せているけど、アプリのIDを変更するだけでいいと思っていました。

Karabiner の既存ルールは frontmost_application_if で画面共有アプリを判定しているので、そこに Screens 5 の bundle ID を足せばいいはず。

"bundle_identifiers": [
    "^com\\.apple\\.ScreenSharing$",
    "^com\\.apple\\.RemoteDesktop$",
    "^com\\.edovia\\.screens\\.5$"
]

Screens 5 の bundle ID は com.edovia.screens.5。ターミナルで確認できる。

osascript -e 'id of app "Screens 5"'

で、ルールは発火するようになった。ローカルのIMEは切り替わる。

が、

リモートが切り替わらないんですよね、ここからが長かったです。

原因その1は、VNC

標準の画面共有.app は、Apple 独自の拡張で Mac の生のキーコード(japanese_eisuu / japanese_kana)をそのままリモートへ運んでくれているんですよね。さすがapple 純正。独自の拡張があるんですよね。だから元記事の方式が成立していた。

Screens 5 は VNC プロトコルで接続する。VNC はキーを「文字」ベースで運ぶ仕組みなので、JIS の英数/かなキーのような特殊キーは、そもそも転送されない様子。

ここから、色々とトライした。

Apple 日本語IMEの標準ショートカット(Ctrl+Shift+J でひらがな、Ctrl+Shift+; で英字)に変換して送る作戦。ダメ。

Screens 5 の接続設定「詳細」にある入力モード(キーストローク / ユニコード / レガシー)を全部切り替えてみる。全滅。orz

かなり四苦八苦したけど、この方向では解決せず。発想を変えることにした。

リモート側で受ける。でも Karabiner では受けられない

リモートも Mac なんだから、届いたキーをリモート側で変換すればいい。リモートにも Karabiner を入れて、送りやすいキー(F18/F19 あたり)を英数/かなに変換する作戦だ。

ところが、ここにも落とし穴がありました。

画面共有で届くキーは、リモートの macOS 上では「ソフトウェアが注入したイベント」になる。Karabiner-Elements が見張っているのは物理キーボード(HID層)だけなので、画面共有経由のキーは Karabiner に見えないらしい。まーそうですよね。キー入力が1つも見えない。

Claudeが、リモート側の受け手は Hammerspoon にすると言い出しまして、僕はまったく知らなかったんですが、これが救世主に。

Hammerspoon の eventtap は、注入されたイベントも見える場所で動いている。

F18 が消える。犯人は、セキュア入力

これで行けると思ったら、まだ動かない。

F18 を送っても、リモートの Hammerspoon まで届いていない。

調べていくと、原因は macOS のセキュア入力(Secure Keyboard Entry)だった。

リモートの loginwindow がセキュア入力を保持したままになっていて、F18/F19 のような通常キーの押下イベントは、イベントタップに届く前に null イベント化されて消えていた。

Claude Codeが、リモート側のキーイベントを収集するプログラムを作り、色々なキーを押して、問題を切り分けていく、すると、

見つけた抜け道があった。

修飾キー(Ctrl や Option)の状態変化イベント(flagsChanged)は、セキュア入力の影響を受けずに届く。

なので、送るキーを「fn+左Control(英数)」「fn+左Option(かな)」という修飾キーだけの組み合わせに変更した。

これなら VNC も通り抜けるし、セキュア入力にも消されない。

最終形の設定

操作側(手元の Mac)の Karabiner は、Screens 5 用のルールを別に作り、リモート向けの送出キーをこうする。

英数: { "key_code": "left_control", "modifiers": ["fn"] }
かな: { "key_code": "left_option",  "modifiers": ["fn"] }

たとえば「左Cmd 単押しで両方を英数に揃える」ルールなら、こうなる。

{
    "description": "Screens 5: 左Cmd 単押し → ローカルとリモートを両方 英数 に同期",
    "manipulators": [
        {
            "type": "basic",
            "conditions": [
                {
                    "type": "frontmost_application_if",
                    "bundle_identifiers": ["^com\\.edovia\\.screens\\.5$"]
                }
            ],
            "from": {
                "key_code": "left_command",
                "modifiers": { "optional": ["any"] }
            },
            "to": [{ "key_code": "left_command", "lazy": true }],
            "to_if_alone": [
                { "key_code": "left_control", "modifiers": ["fn"] },
                {
                    "select_input_source": [
                        { "input_source_id": "com.apple.keylayout.ABC" }
                    ]
                }
            ]
        }
    ]
}

ローカル側の切り替えは元記事と同じ select_input_source。リモート向けの送出キーだけが変わった形だ。

標準の画面共有.app 用の元のルールはそのまま残してあるので、アプリによって送り方が自動で切り替わる。

karabiner.json をいじる前には、必ずバックアップを取ってください。

リモート側は、Hammerspoon をインストールして、~/.hammerspoon/init.lua にこれを書く。

-- 画面共有から届く fn+ctrl / fn+option で入力ソースを切り替える
local JA_IDS = {
  "com.apple.inputmethod.Kotoeri.RomajiTyping.Japanese", -- Apple 日本語IME
  "com.google.inputmethod.Japanese.base",                -- Google 日本語入力
}
local function setJapanese()
  for _, id in ipairs(JA_IDS) do
    if hs.keycodes.currentSourceID(id) then return true end
  end
  return false
end
local function setEisuu()
  hs.keycodes.currentSourceID("com.apple.keylayout.ABC")
end

local lastFlagTrigger = 0
imeFlagTap = hs.eventtap.new({ hs.eventtap.event.types.flagsChanged }, function(e)
  local f = e:getFlags()
  local now = hs.timer.secondsSinceEpoch()
  if now - lastFlagTrigger < 0.3 then return false end
  if f.fn and f.ctrl and not (f.alt or f.cmd or f.shift) then
    lastFlagTrigger = now; setEisuu(); hs.alert.show("英数", 0.4)
  elseif f.fn and f.alt and not (f.ctrl or f.cmd or f.shift) then
    lastFlagTrigger = now; setJapanese(); hs.alert.show("かな", 0.4)
  end
  return false
end)
imeFlagTap:start()

hs.alert.show("IME 切替設定 読み込み完了", 1)

日本語入力ソースのIDは環境で違うので、リモートで確認して JA_IDS を合わせる。

defaults read com.apple.HIToolbox AppleEnabledInputSources

そして、ここが重要。Hammerspoon に与える権限は、システム設定の「アクセシビリティ」と「入力監視」の2つとも必要になる。

アクセシビリティだけだと、イベントタップは「有効」と報告されるのにキーが1つも届かない、という無言の失敗になる。ここで悩む時間がもったいないので、最初から両方許可してください。

これで、Screens 5 の画面越しに英数キーを押すと、リモートの画面に「英数」とポップアップが出て、両方のIMEが揃う。かなキーなら「かな」。ポップアップが出るので、届いているかどうかが目に見えるのも安心感がある。

ちなみに、動作確認が済んだあとは、このポップアップは、切り替えのたびに表示が出るのが煩わしくなってきたので、hs.alert.show("英数", 0.4)hs.alert.show("かな", 0.4) の2行を削除(かコメントアウト)して、Reload Config をClaude Codeに依頼した。

まとめ

Screens 5 での画面共有IME同期、整理すると以下の感じに。

操作側の Karabiner が「英数 = fn+左Control、かな = fn+左Option」を送出。

VNC とセキュア入力を通り抜けた修飾キーイベントを、リモートの Hammerspoon が受けて入力ソースを切り替える。ローカル側は従来どおり select_input_source で同時に切り替え。

原因が「VNC の仕様」と「セキュア入力」の二段構えだったので、切り分けにはだいぶ時間がかかった。

実は、今回の調査は、操作側とリモート側、それぞれの Mac で動かしている Claude Code に手伝ってもらった。というより、1行もコードは書いていない、全部、話言葉で指示を出しただけ。すごい時代になったと痛感する。

操作側の Claude Code にリモート用の指示プロンプトを書いてもらい、それをリモートの Claude Code に貼る、という伝言ゲームをやっただけ。

セキュア入力が通常キーを null イベント化している、という核心はリモート側の解析で見つかった。二人三脚ならぬ、二AI三脚。

動いた瞬間は、ホッとしたというより、嬉しかった。

Screens 5 に乗り換えて英数/かなキーの同期が効かなくなって困っている方は(かなりニッチだと思うけれど)、お試しください。

この記事を書いた人

大東 信仁

カンパチが好きです。

プロフィールはこちら

10月14日開催 参加者募集中
(画像をタップ→詳細へ)

ミッションナビゲート モニター
(画像をタップ→詳細へ)

広告