2021-09-02

OSのIME関連APIとWebブラウザは相性が悪い

今どきのWebブラウザは複数のプロセスで動くことが前提になっている。Chromeで言えば、メイン(UI)プロセスとレンダラープロセス。Firefox用語であればChromeプロセスとコンテンツプロセスという感じで別れて動作している。Webコンテンツはコンテンツ用のプロセスで表示され、文字入力はUI用プロセスで動作している。だから入力された文字はコンテンツ用のプロセスへプロセス間通信で送られ、コンテンツ用プロセスで内部的に描画されるいることになる (実際に画面上に描画されるのがGPUプロセスだったりUIプロセスだったりするけど)。

今どきのOSで使われるIMEのためのAPIは入力された文字をただアプリケーションに渡すだけではなく、様々なことを要求してくる。例えば文字変換の精度を上げるために現在入力している場所周辺の文字情報をアプリケーションへ要求したり、文字変換用パネルウィンドウの表示位置を決定するために、アプリケーションが文字入力している表示座標の問い合わせをアプリケーションへ行ったりする。

Webブラウザは反応速度を上げるため、基本的にはブロッキングするようなプロセス間通信を許可しない (もちろん例外がないわけではないが)。プロセス間通信は基本的に非同期で行われてる。たとえば、コンテンツ用プロセスがビジーな状況というのは結構ありがちな状況で、その状況下で同期モデルなプロセス間通信を使うと、当然のことながら、そのプロセス間通信が正常終了するまでに長い時間がかかり、反応速度が非常に悪くなる。なので基本的には非同期なプロセス間通信を利用している。

この非同期なプロセス間通信のみを許可するというところが、非常にIME関連APIとの相性を悪くしている。なぜなら多くのケースでこれらのAPIが非同期API (例えば引数で渡されたコールバック関数経由で値を渡す) ではなくて、同期APIになってたりする。または、非同期的なレスポンス (エラーコードとして、今はPendingだからまた問い合わせてねというものを返す) を返すことが可能であっても、そのエラーコードを見てくれなかったりなど、まぁWebブラウザがこういうモデルを要求しているというニーズにIME関連APIがマッチしてない。APIデザインが最後発であるAndroidでさえ、残念ながらここらがすべて非同期になってない。

そんなこと言っていても、OS側がこちらの欲しいAPIを実装してくれるわけでもないので、ChromeもFirefoxもいろんな手を使ってこの状況下でもIMEを動かすようにしている。ただうまく行かないケースになった場合、例えばIMEの候補ウィンドウが間違った場所に表示されてしまったりするのは、これらのブラウザ側のハックがうまく動かなかったケースになる。Android版になると、メインプロセス内でもブラウザのメインスレッドとAndroidのUIスレッドが別になるので、より複雑さを増したりする。

なお、Apple (macOS) はWebKit2のときにこの問題を解決するめに非公開の非同期API群を作って対処した。Appleズルい