この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2015年4月)

2015年4月17日

Bug-org 1137539 [TSF] Workaround for TS_E_NOLAYOUT bug of <= Windows 8.1 may need to check different TIP name for different language Windows 初回投稿日時: 2015年04月17日10時39分55秒
最終更新日時: 2015年04月17日10時58分39秒
カテゴリ: Mozilla Core Mozilla40 TSF Windows バグ修正
固定リンク: id=2015041700
SNS: (list)

TSFには、ITextStoreACP::GetTextExt()から、TS_E_NOLAYOUTを返しても、TIPにはE_FAILが返されてしまうので、レイアウトの再計算の終了を待つことができないというバグがあります(このバグはWindows 10では修正されている模様)。

このバグに個別に対応するため、問題が判明しているTIPの名前ごとに、必要なハックを用いて、「それっぽい位置」を返して、問題が無いかのように見せていますが、Google日本語入力の存在で、Windowsの言語が変わると、TIPの名前も変わっている可能性があることが分かりました。そこで、これまでにハックを行ったTIPを全て、そのターゲットとしている言語バージョンのWindowsと、英語版のWindowsで名前を確認していきました。

幸い、Google日本語入力以外では、Windowsの言語に関係無く、同じ文字列が名前として利用されていましたので、このバグ修正では、それぞれを確認するためのコードをTSFStaticSinkのメソッドにしてしまうことで、定数まみれだったコードを綺麗にしています。

Bug-org 1151186 Japanese IME input is not working Google spreadsheet 初回投稿日時: 2015年04月17日10時57分55秒
カテゴリ: Mozilla Core Mozilla40 TSF バグ修正
固定リンク: id=2015041701
SNS: (list)

Googleスプレッドシートで日本語入力中に、一度、他のアプリをアクティブにして、再びFirefoxにフォーカスを戻すと、TSFと、IMMを問わず、しかし、症状が異なるバグり方で、正常に日本語入力ができなくなるというバグです。

調査してみると、すぐに、IMEの状態管理に問題があることが分かりました。最初にスプレッドシートを開くと、どのセルも編集モードになっていなくても、IMEをオンにできてしまいます。また、スプレッドシートを表示している状態で設定タブを開き、スプレッドシートのタブに戻ってくると、セルの編集を開始しても、IMEが無効になったままでした。

そこで、IMEStateManagerのログ等からGoogleスプレッドシートの挙動を調べて見ると、まず、ドキュメントがフォーカスを得た時に、contenteditableな要素にフォーカスを移動させている事が分かりました。ただ、問題は、ドキュメントのfocusイベントハンドラ内で、フォーカスを移動させていたことにあります。このため、ドキュメントがフォーカスを得たことで、IMEを無効化しようとしますが、それを行う前に、エディタがフォーカスを得ることで、IMEを先に有効化してしまいます。そしてその後で、ドキュメントのフォーカス処理に戻って、IMEの無効化が完成します。

まず、最初のパッチでは、ドキュメントのフォーカス処理の最中に、別の要素にフォーカスが移動していたら、IMEの状態管理は(既に行われているはずなので)行わないように修正しました。

しかし、これだけではうまく動作しませんでした。さらに調査してみると、Googleスプレッドシートは、フォーカスの移動をブラウザに任せておらず、ドキュメントがフォーカスを得るときに、自身でフォーカスを行ったん別の要素に設定し、その後、元のフォーカスを持っていた要素にフォーカスを設定するということを行っていました。

ドキュメントにひとつしか存在しないnsHTMLEditorは、入力イベントが来る度に、自分自身が管理すべき要素がフォーカスを持っているのかどうかを検査します。しかし、Googleスプレッドシートの自前フォーカス管理によって、この検査で「フォーカスを持っていない」と判断し、一部のCompositionEventを捨て、フォーカス移動によって発生している強制確定のリクエストを無視してしまっていました。

以前より、CompositionEventは、TextCompositionクラスが、compositionstartからcompositionendまで、必ず同じ要素上で発火するようにしています。そこで、これを利用して、nsHTMLEditorCompositionEventのターゲットが自分自身が管理しなくてはいけない要素のうちの一つであれば、フォーカスを持っていなくても処理を行う様に修正しました。

Bug-org 1124608 Support D3E EventModifierInit 初回投稿日時: 2015年04月17日12時28分48秒
最終更新日時: 2015年04月18日00時10分22秒
カテゴリ: Events Mozilla Core Mozilla40 バグ修正
固定リンク: id=2015041702
SNS: (list)

D3Eでは、各種イベントを生成する時に、dictionaryを用いた、簡単な記述で互換性の問題も発生しにくいコンストラクタが提案されています。基本的にはこのdictionaryは生成後にそのイベントの属性名になるものをキーとして値を設定します。例えば、

var keyboardEvent = new KeyboardEvent("keydown",
  { key: "Tab", code: "Tab", keyCode: 9, shiftKey: true });

しかし、D3EではKeyboardEvent.getModifierState()や、MouseEvent.getModifierState()で、キーとして定義されている全てのモディファイアの状態や、Accelといった仮想モディファイアも状態を検査できるようになりました。しかし、逆に言うと、これらが属性という形式をとっていないため、Javascriptがイベントを生成する時に初期化する方法がありませんでした。

そこで、EventModifierInitが新たに提案され、今回はこれの実験実装を行いました。これにより、例えば、CapsLockと、OStrueにしたい場合、以下のように記述できます。

var keyboardEvent = new KeyboardEvent("keydown",
  { key: "Tab", code: "Tab", keyCode: 9,
    modifierCapsLock: true, modifierOS: true }

Bug-org 1152229 Define new code value "FnLock" 初回投稿日時: 2015年04月17日12時51分25秒
カテゴリ: Events Mozilla Core Mozilla40 バグ修正
固定リンク: id=2015041703
SNS: (list)

D3Eでは、Microsoft製のマルチメディアキーボードに付いている、FLockというキーを、一応定義しています。これは通常のOS上のアプリからは全く見えない特殊なキーです。

このキーを、key値ではFnLockcode値ではFLockと定義されていましたが、このミスマッチはおかしいので、W3Cにバグを投げていましたが、ようやくFnLockで統一されたので、code値にFnLockを追加しました(FLockはこのミスマッチに気付いていたので、もともとサポートしていませんでした)。

Bug-org 492394 [TSF] Implement nsTextStore::GetACPFromPoint 初回投稿日時: 2015年04月17日13時11分12秒
最終更新日時: 2015年04月18日00時11分19秒
カテゴリ: Mozilla Core Mozilla40 TSF Windows バグ修正
固定リンク: id=2015041704
SNS: (list)

今のところ、ITextStoreACP::GetACPFromPoint()を活用しているTIPを見つけていないような状態でしたので、今まで実装していませんでしたが、これから、TSFをFirefoxで標準機能とした場合には、新しいTIPがこの機能を利用した時に、Firefoxが実装していなければ利用を断念するかもしれません。そんな状況はよくないので、今回、ある程度実装を行いました。

GXFPF_ROUND_NEARESTGXFPF_NEARESTが指定されていて、指定位置に文字が無い場合、その場所をクリックしたときにキャレットが移動する場所を返します。

GXFPF_NEARESTのみが指定されていて、指定位置に文字が無い場合、簡単にその位置に近い文字を探すAPIが残念ながらGecko内には存在していないため、このケースの実装のみ、正確性を欠いたものになっています。このケースでは、基本的に、その位置をクリックした場合のキャレット位置を返します。ただし、最後の文字の右側に来る場合は、ひとつ引いた値になります(文字の最大値は、キャレット位置の最大値 - 1なため)。これは、大きく異なる座標を返すことはありませんが、その座標から近い文字の右半分にヒットしている場合、ひとつ右側の文字のインデックスを返すことになります。

Bug-org 1154161 Initialize all members of WidgetQueryContentEvent::mReply for safer behavior even if they are referred accidentally 初回投稿日時: 2015年04月17日13時16分40秒
カテゴリ: Mozilla Core Mozilla40 バグ修正
固定リンク: id=2015041705
SNS: (list)

widgetがフォーカスを持っているエディタの内容を調査する時に利用している内部イベントのWidgetQueryContentEvent、その調査結果はmReplyに格納されるのですが、イベントの種類によって、どのメンバーが更新されているのかが変わります。

これまではパフォーマンス重視で、初期化を行っていませんでしたが、もし、更新されない値を誤って参照した場合に、危険なクラッシュ等を引き起こさないように、全てのメンバを安全な値で初期化しておくように修正しました。

Bug-org 478029 [MSFT-7923] [MSFT-10204] [TSF] enable TSF support in default prefs on Vista or later 初回投稿日時: 2015年04月17日13時30分16秒
最終更新日時: 2015年04月18日00時13分05秒
カテゴリ: Mozilla Core Mozilla40 TSF Windows バグ修正
固定リンク: id=2015041706
SNS: (list)

ついに、TSFモードがリリース版でもデフォルトで有効になることになりました。

古くから、現在はMozilla Japanのエンジニアである加藤誠さんからTSFに対応すべきだというバグ報告がありました。これが2001年7月2日のことです。

その後、話が私のところに来ましたが、私は当時、寝耳に水の話でしたし、ドキュメントを読んでもまったく理解できなかったので、手つかずのまま放置されていました。

大きく状況が動いたのは2008年7月5日でした。現在、Firefox for AndoidのキーボードやIME周りを一手に担当している、Jim ChenがGoogle Summer of Codeで、TSFモードの実装を開始しました。

彼のおかげで、おおまかに動くところまでは行ったのですが、Windows XP日本語版に標準搭載されていたNatural Inputの挙動がトリッキーだったり、そもそも、Windows XPのTSF自体に問題が多く、実用化には至りませんでした。

その後、TSFを実装するのに足りない機能や、不便だった点をGecko側で修正しつつ、TSF対応のコードも私が引き継いで、徐々に改善を続けていました。

そしてついに、現在報告されている深刻なバグの修正が全て終了したので、今回、リリース版でもデフォルトで有効にすることにしました。既にAurora (Developer Edition)では39から標準で有効になっていますので、Auroraで2サイクル、Betaで1サイクル、Nightly以外のテスタからのフィードバックも期待しています。この間に特に深刻な問題が報告されなかった場合は、40からリリース版でも有効になることになります。