Bug-org 1208043 [TSF] MS-IME for Korean inserts composition string to the end of previous textnode when you type text at start of <p>
初回投稿日時: 2015年10月31日10時37分20秒
カテゴリ: IME Mozilla Core Mozilla42 Mozilla43 Mozilla44 TSF Windows バグ修正
SNS:
Tweet (list)
contenteditable
でEnterキーを押した時の動作には2種類あって、<div contenteditable>foo</div>
というエディタ上では<br>
要素が挿入し、キャレットのその後ろに移動させますが、<div contenteditable><p>foo</p></div>
というエディタで(<p>
要素内にキャレットがある時に)は新しい<p>
要素を生成して、その内部にキャレットを移動させます。このバグは後者の場合に、Enterキーを押した直後、つまり空の<p>
要素でハングル文字を入力しようとすると、ひとつ前の<p>
要素の最後に入力されてしまうというバグです。
まずそもそも何故このようなことが発生しているのかというと、ハングル用のMS-IMEは非常に特殊な挙動で未確定文字列の入力開始を通知してきている点にありました。普通のTIPは、ITfContextOwnerCompositionSink::OnStartComposition()
を呼び出して、明示的に未確定文字列の編集が始まったことをアプリに通知してから、文字の入力や、選択範囲の設定を行います。それに対してハングル用のMS-IMEは、先にITextStoreACP::InsertTextAtSelection()
を呼び出し、最後にITfContextOwnerCompositionSink::OnStartComposition()
をその時に期待される選択範囲と共に呼び出します。
このような順序のため、TSFTextStore
は、まずテキストの挿入が未確定文字列の編集無しに行われ、その後、別の範囲をターゲットに未確定文字列の編集が開始されたと考えていました。ですので実際に、最初の編集に対してcompositionstart
、compositionupdate
、compositionend
を送信した後、compositionstart
が再度送信されるという動作になってしまっていました。
そして、何故、挿入位置がずれてたかというと、現在、GeckoがDOMツリーからIME APIに対して渡すコンテンツの内容は<br>
要素のみを改行文字に変更したプレーンテキストになっています(ContentEventHandler
で生成)。このため、<p>foo</p><p></p>
というDOMツリーでは、空の<p>
要素内にキャレットがある場合のオフセットと、最初の<p>
要素の末尾(つまり、foo
テキストノードの末尾)のオフセットが同じになってしまいます。未確定文字列が指定された範囲で変換が開始されるこのケースでは選択範囲を再設定しなくてはいけませんが、選択範囲をContentEventHandler
を利用して設定した場合、常に、後者の位置が優先されてしまうため、このようなバグの発生につながっていました。
今回の修正では、未確定文字列の編集が開始される際に、直前に行われてキューに入っている内容を確認し、直前の内容がITfContextOwnerCompositionSink::OnStartComposition()
の指定してきた範囲に直接文字を挿入していた場合、compositionstart
、compositionupdate
、compositionend
をキューから取り除き、新たにcompositionstart
とcompositionupdate
をあるべき形でキューに入れ直すことでContentEventHandler
側のオフセットの矛盾問題に触れないように修正しました。