Android でも言語切替をトグルではなく直接指定にできないか (ユーザー補助サービスの検討)

Open
#55 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
android, c

Research direction

First test Key Mapper’s “Switch keyboard” action on a real device, then use a key tester to check which dedicated key codes Android can distinguish. If both tests succeed, inspect the Android branch of td_tap_confirm() in firmware/windmill.c and determine which dedicated keys it should send. Done means the Android mode can select Japanese and English directly; otherwise, leave Android using the toggle.

Written by the indexing model from the issue text.

Description

背景

issue #53 / PR #54 で、Ctrlタップの言語切替をトグルにした。Windows は KC_LNG1 (かな) / KC_LNG2 (英数) を交互に送るので、IME側とずれてももう一度タップすれば揃う。

Android だけがトグル (Ctrl+Space) のままで、IME側を別の手段で切り替えてずれると、キーボードのベースレイヤーと食い違ったまま自力では戻せない。

Android で KC_LNG1/KC_LNG2 自体は効くが、日本語IMEが入力欄を移るたびに既定のかなへ戻ってしまい、英数を保てない。そのため、IMEそのもの (日本語⇔英語) を切り替える形にしてある。

このissueは、Android でもモードを直接指定できないか調べた結果のメモ。実機では何も試しておらず、以下はすべて公開ドキュメントを読んだ範囲の話。

分かったこと

  • Android 11 (API 30) 以降、ユーザー補助 (アクセシビリティ) サービスは SoftKeyboardController.switchToInputMethod(imeId) で IMEを名指しで切り替えられる。条件はその IME がインストール済みかつ有効なこと。戻り値で成否が分かる
  • ユーザー補助サービスは、物理キーのイベントを IME やアプリより先に受け取れる (FLAG_REQUEST_FILTER_KEY_EVENTS)。握りつぶすこともできる
  • つまり、キーボードが「日本語へ」「英語へ」の専用キーを送り、常駐するサービスがそれを受けて IME を切り替えれば、Windows と同じくモードを直接指定する形にできる。ずれてもタップし直せば揃う

制約

  • 切り替えられるのは IME 単位。 Gboard の中の日本語と英語は同じ IME の中の「サブタイプ」で、これを外部のアプリから選ぶ公開APIは無さそう (setCurrentInputMethodSubtype / setInputMethodAndSubtype は非推奨か、IME自身・システム専用)
  • したがって 英語側を別の IME にする必要がある。 Key Mapper の "Basic Input Method" は画面キーボードを持たない IME なので、物理キーボード専用なら足りそう
  • 物理キーボードの配列 (英語(US)) は IME ごとの設定。 英語用の IME にも設定し直す必要があるかもしれない

まずコードを書かずに試す

Key Mapper (オープンソース) がまさにこの仕組みで動いていて、アクション一覧に Switch keyboard がある。

  • 専用キーA → Gboard (日本語)
  • 専用キーB → 英語用の IME

これで想定どおり動けば、自作アプリはほぼ同じことをするだけで、ユーザー補助サービスと設定XMLで数十行程度に収まるはず。

ただし Switch keyboard が Android 11 以降で追加の権限なしに特定の IME を選べるかは、ドキュメントに書かれておらず未確認。

気をつけること

  • 専用キーは新しく用意する。 KC_LNG1/KC_LNG2 は Symレイヤーの数字・記号と、かなの「も」の Shift+タップ (半角?) で一時的な切り替えに使っているので、サービスが横取りすると壊れる
  • そのキーが Android に区別できる形で届くか要確認。 Android の KeyEvent は F1〜F12 までで、F13以降は「不明なキー」扱いになる可能性がある。キーテスターのアプリで先に確かめる
  • Android 13以降、ストア外から入れたアプリのユーザー補助を有効にするには「制限付き設定を許可」の手順が要る
  • 機種によっては省電力機能でサービスが止められることがある
  • すべてのキー入力がサービスを通る。自作なら問題ないが、他人のアプリを使うなら信頼できるかの話になる
  • 別の方法として、adb で WRITE_SECURE_SETTINGS を与えて既定のIMEの設定を書き換えるやり方もあるが、公式に用意された手段であるユーザー補助のほうが素直

ファームウェア側に要ること

Android モードのとき、Ctrl+Space の代わりに専用キーを切り替え先に応じて送るよう、firmware/windmill.c の td_tap_confirm() の Android 分岐を変えるだけ。PR #54 の作りにそのまま載る。

進め方

  1. Key Mapper で Switch keyboard が期待どおり動くか実機で確認する
  2. 専用キーに使えるキーコードを実機で探す
  3. 動けばファームウェア側を直し、常駐アプリを自作するか Key Mapper に任せるかを決める

1と2が通らなければ、Android はトグルのままにする。

アイデア: 英語用の IME を自作する

Android で専用の英語用 IME を作り、英語モードにするときはその IME を強制的にアクティブにしてモードを揃える。特定の IME を強制的にアクティブにできるかを、実現性として探る。

調査結果: ソースから分かったこと (2026-11-03)

AOSP、Linux、Key Mapper のソースを読んで分かったこと。実機では確かめていない。

専用キーの候補

キーボードから送ったキーは、Linux の hid-input.c でキーコードに変わり、AOSP の Generic.kl で Android の KEYCODE_* になる。

QMK HID Linux Android
KC_INT2 0x88 KEY_KATAKANAHIRAGANA (93) KATAKANA_HIRAGANA
KC_INT4 0x8A KEY_HENKAN (92) HENKAN
KC_INT5 0x8B KEY_MUHENKAN (94) MUHENKAN
KC_LNG5 0x94 KEY_ZENKAKUHANKAKU (85) ZENKAKU_HANKAKU
KC_LNG3 / KC_LNG4 0x92 / 0x93 KEY_KATAKANA / KEY_HIRAGANA 対応なし (Generic.kl でコメントアウト)
KC_F13〜KC_F24 0x68〜0x73 KEY_F13〜KEY_F24 F13〜F24。KEYCODE_F13 以降は 2025年Q2 の新しいキーコードで、それより前の Android では不明なキー
  • 候補は KC_INT4 (変換) と KC_INT5 (無変換) の組。どの Android でも別々のキーコードで届き、windmill はどちらもまだ使っていない。日本語へ = 変換、英語へ = 無変換で、意味も合う
  • サービスが動いていないときは、変換・無変換がそのまま IME に届く。F13 以降なら何も起きないが、古い Android ではキーコードで区別できない
  • Key Mapper は、キーコードが不明なキーをスキャンコードで見分ける (CHANGELOG #1276、#761)。F13 以降でも Key Mapper なら使える
Key Mapper の Switch keyboard

SwitchImeAsyncImpl.kt と BaseAccessibilityService.kt を読んだ。

  • Android 11 以降は、ユーザー補助サービスの switchToInputMethod(imeId) で切り替える。追加の権限は要らない
  • 失敗したときだけ、WRITE_SECURE_SETTINGS (adb で付与) があれば DEFAULT_INPUT_METHOD を書き換える
  • 切り替え先の IME は、あらかじめ有効にしておく必要がある
自作する場合の形
  • 1つのアプリに、英語用の IME とユーザー補助サービスを同梱する
  • Android 13 以降、ユーザー補助サービスは同じパッケージの IME を、ユーザーの操作なしで有効にできる (setInputMethodEnabled。Key Mapper も同じ制約で使っている)。英語用 IME を設定画面で有効にする手順が要らない
  • 英語用 IME は、画面キーボードを持たない InputMethodService の派生だけで足りる。キーは処理せず、アプリへ素通しする。Key Mapper の KeyMapperImeService.kt が参考になる
  • ユーザー補助サービスは、onKeyEvent で変換・無変換を受けて握りつぶし、switchToInputMethod を呼ぶだけ
  • 規模は、Kotlin のコードが2クラスで100行前後、ほかに manifest と設定の XML が2つ
実機で確かめること
  1. 変換・無変換を送ったとき、キーテスターに KEYCODE_HENKAN / KEYCODE_MUHENKAN で届くか
  2. Key Mapper で、変換 → Gboard、無変換 → 英語用 IME の切り替えが効くか
  3. 英語用 IME に切り替えたとき、物理キーボードの配列 (英語(US)) がそのまま効くか

進め方の更新 (2026-11-03)

Key Mapper は機能が多すぎるので、試さずに自作へ進む。

  • アプリ: cognitom/windmill-android (#1 アプリ本体、#2 ビルド環境)
  • ファームウェア: #105 (アプリが実機で動いてから)
Dominant language
C++
Stars
4
Forks
0
Avg merge
1h 56m
Merged PRs (30d)
15

Getting set up

  • Ships a Dockerfile or Docker Compose file
  • No pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cognitom/windmill

All issues in cognitom/windmill

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.