IMEと入力モードの変更

sennという名前のWindowsで動くIMEを自作しています。 sennの言語バーには入力モードを表示・切り替えるボタンがあり、このボタンをクリックするとひらがな入力と直接入力とを切り替えることができます。 この振る舞いは単純なのですが、内部実装はちょっと複雑になっているためここにメモしておきます。

sennはネットワークでつながったフロントエンドとバックエンドで構成されています。 sennの状態はすべてバックエンドで保持されており、入力モードもバックエンド側で管理してます。 フロントエンドは画面の表示のみを担当しています。

入力モードを表示・切り替えるボタンにはITfLangBarItemButtonを利用しています。 ユーザーがこのボタンをクリックすると、以下のように処理が進みます。

  • Windowsが(?)フロントエンドにあるボタンのITfLangBarItemButton::OnClickメソッドを実行する
  • フロントエンドがバックエンドに対して入力モードを切り替えるメソッド (ToggleInputMode) を実行する
  • フロントエンドがWindowsに (?) 対してアイコンアップデートメソッド (ITfLangBarItemSink::OnUpdate(TF_LBI_ICON))を実行する
  • Windowsが(?)フロントエンドにあるボタンのGetIconメソッドを実行する
  • ボタン (のコールバック) がバックエンドに対して現在の入力モードを問い合わせる (GetInputMode)
  • フロントエンドが入力モードに応じてアイコンを返却する

シーケンス図は次の通りです。

f:id:mhkoji:20211104203759p:plain
シーケンス図

ITfLangBarItemButtonのアイコンを更新するにはボタン自身にGetIconメソッドでアイコンを返却させるという仕組みになっているようで、 外側からsetterでボタンのアイコンを指定するようなことはできなさそうでした。 この事情により、バックエンドはToggleInputModeメソッドとGetInputModeメソッドを提供しており、 ToggleInputModeでは更新後の入力モードを返却せず、 GetIconメソッド用のGetInputModeメソッドが別途入力モードを返却するようにしています。

おわりに

ネットワーク越しに状態を更新し、参照するのは、大げさな感がありますが、面白いです。 なお、バックエンドのToggleInputModeGetIconの処理を担当しているのはstateful-imeです。