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

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

もずはっく日記(2013年9月)

2013年9月30日

Bug-org 911463 nsDOMUIEvent::IsChar() casts nsTextEvent* as nsKeyEvent* 初回投稿日時: 2013年09月30日21時11分17秒
カテゴリ: Events Mozilla Core Mozilla26 バグ修正
固定リンク: id=2013093000
SNS: (list)

GeckoのDOM KeyboardEventと、TextEventにはisCharというプロパティがありますが、TextEvent.isCharの取得時に、間違えたキャストを行って、正しい値を返していなかったというバグです。

isCharの値は、nsKeyEventと、nsTextEventのメンバに保存されているので、それぞれに正しくキャストしてアクセスしなくてはいけないのですが、nsTextEventのインスタンスであっても、nsKeyEventにキャストしてアクセスしていました。

見つけた時は焦ったのですが、調べたところ、32bit版でも、64bit版でも、クラスのインスタンス内を参照しているので、クラッシュすることはありません。返ってくる値がデタラメなだけでした。

このバグ自体は修正しましたが、そもそも、nsTextEvent::isCharは正しく初期化されていないプラットフォームの方が多い上に、他のブラウザには存在しない非標準イベントですので、参照しないようにしてください。

Bug-org 910978 Implement Assign*EventData() for all ns*Event 初回投稿日時: 2013年09月30日21時20分13秒
カテゴリ: Events Mozilla Core Mozilla26 バグ修正
固定リンク: id=2013093001
SNS: (list)

全ての内部イベントクラスにメンバをコピーするメソッドを実装しようというバグです。

もともとは、nsDOMEventで、変数に保存されたDOMイベントのディスパッチが終わった後にも、各プロパティにアクセスできるようにするために、コピーしていただけだったので、nsDOMEvent内で直接行われていました。このため、nsGUIEvent.h内でイベントクラスにメンバを追加しても、ここの修正を忘れていたり、Bug-org 910156のようなバグの温床になるので、クラスの定義部分で確実に管理できるようにしようというのが、このバグ修正の理由となっています。

コピーコンストラクタを作れ、という意見もあるかと思いますが、イベント全体を丸ごと単純にコピーする、という用途は皆無なので、あえて、通常のコンストラクタでインスタンス生成後に、内容を条件に応じてコピーするメソッドを利用するという形になっています(strong referenceなメンバを含んでいるので、単純なコピーを許可すると、メモリリークバグを産みやすくなってしまうため)。

Bug-org 911951 nsIDOMWindowUtils::SendTextEvent() should be able to treat 4 or more clauses 初回投稿日時: 2013年09月30日21時36分49秒
カテゴリ: Firefox OS Mozilla Core Mozilla26 バグ修正
固定リンク: id=2013093002
SNS: (list)

nsIDOMWindowUtils::SendTextEvent()は、trustedなnsTextEventイベントをJavascriptから生成し、IMEの未確定文字列や、確定文字列を擬似的に生成するAPIです。ただし、これは自動テストで、XPレベルのIMEハンドリングを検査するために設計したものなので、未確定文字列内を最大で3つの文節にしか区切れませんでした。ところが、Firefox OSでは、このAPIをIMEの未確定文字列生成に使うことになってしまったので、日本語のIMEの開発には大きな障害となっていました。その制限を無くそうというのがこのバグです。

このバグでは、nsIDOMWindowUtils::SendTextEvent()を廃止し、nsIDOMWindowUtils::CreateCompositionStringSynthesizer()というAPIを追加しました。これを呼び出すと、nsICompositionStringSynthesizerというインターフェースを持った、XPCOMオブジェクトのインスタンスが生成され、返されます。

nsICompositionStringSynthesizerのインスタンスは、そのDOM windowへのweak referenceを保持していて、このwindowが生存している限りは再利用可能になっています(実際に再利用しているコードはありませんが)。

nsICompositionStringSynthesizer::SetString()で未確定文字列、もしくは確定文字列を指定します。

nsICompositionStringSynthesizer::AppendClause()で、文節の長さと、属性を指定し、文節を追加します。これはメモリ容量が許す限り、何度でも呼び出すことができますので、最大、未確定文字列の文字数分の文節を作り出すことができます。確定文字列生成の場合は呼び出してはいけません。

nsICompositionStringSynthesizer::SetCaret()はキャレットの位置と長さを指定できますが、Gecko自体は、1文字以上に渡る、ワイドキャレットはまだサポートしていませんが、一応指定自体は可能です。これは、不要なら呼び出す必要はありません。

最後に、nsICompositionStringSynthesizer::DispatchEvent()を呼び出すと、イベントをディスパッチし、全ての情報がクリアされ、再利用可能な状態になります。

ちなみに、nsICompositionStringSynthesizer::DispatchEvent()が呼び出された際に、文節情報や、キャレット情報が、文字列の長さに対して矛盾している場合、例外が発生し、イベントのディスパッチには失敗しますが、全ての情報はクリアされ、再利用可能な状態になります。

Bug-org 768287 keydown event's getModifierState() returns wrong value on GTK if the key has lockable modifier but the keyval doesn't correspond to a DOM modifier 初回投稿日時: 2013年09月30日21時47分58秒
最終更新日時: 2013年09月30日21時48分20秒
カテゴリ: Events GTK Mozilla Core Mozilla26 バグ修正
固定リンク: id=2013093003
SNS: (list)

以前にも紹介しましたが、LinuxのGTK (GDK)では、キーイベントが発生した段階では、モディファイアのフラグがそのキーが押された状態を反映した値に変化していません。例えば、Shiftキーを押したイベントの、モディファイアフラグの値は、Shiftキーが押された状態にはなっていません。これは、他のプラットフォームの動作とは異なっているため、Geckoでは、キーのハードウェアキーコードから、アクティブになるフラグを予想して、わざわざセットする、ということをやっていました。

しかし、その処理にバグがあり、JISキーボードで、CapsLockキーをShift+英数に割り当てている場合、Shiftキー無しで、英数キーだけを押した場合に、KeyboardEvent.getModifierKey("CapsLock")trueを返していました。

今回の修正では、ハッキーな推測をやめ、XKB Extentionのモディファイアフラグの変更イベントをキーイベントを受け取ったときに、キューに来ていないか調査し、存在する場合には補完するというコードになりました。これで同種のバグがあったとしても一掃されているはずです。

Bug-org 912956 Separate nsGUIEvent.h to a few header files 初回投稿日時: 2013年09月30日22時25分47秒
最終更新日時: 2013年09月30日22時29分07秒
カテゴリ: Events Mozilla Core Mozilla26 Mozilla27 バグ修正
固定リンク: id=2013093004
SNS: (list)

長年の悲願だった、Geckoの内部イベントリファクタリングを実行することを決意しました。まず、このバグでは、肥大化したnsGUIEvent.hを複数のヘッダファイルに分割し、イベント関連のコードを修正した場合に、リビルドする範囲を軽減しようというのがまずは第一目標としました。

まず、イベントクラスのリネームもこの機会に行うため、まずは、nsEvent.hと、nsGUIEvent.hで定義されていた、mozilla::widget名前空間のものをmozilla名前空間に移しました。これだけは、Mozilla 26で修正されています。

これ以降は、Mozilla 27での修正になります。

各イベントクラスや、関連する構造体の前方宣言を行っている、nsEvent.hは、mozilla/EventForwards.hにリネームしました(ソースコードは、widget/EventForwards.hです)。

次に、イベントの種類ごとに、以下のようにヘッダファイルを分割しました。

mozilla/BasicEvents.h
  • enum nsEventStructType
  • イベントメッセージ
  • mozilla::BaseEventFlags
  • mozilla::EventFlags
  • mozilla::WidgetEvent (旧nsEvent)
  • mozilla::WidgetGUIEvent (旧nsGUIEvent)
  • mozilla::WidgetInputEvent (旧nsInputEvent)
  • mozilla::InternalUIEvent (旧nsUIEvent)
mozilla/ContentEvents.h
  • mozilla::InternalScriptErrorEvent (旧nsScriptErrorEvent)
  • mozilla::InternalScrollPortEvent (旧nsScrollPortEvent)
  • mozilla::InternalScrollAreaEvent (旧nsScrollAreaEvent)
  • mozilla::InternalFormEvent (旧nsFormEvent)
  • mozilla::InternalClipboardEvent (旧nsClipboardEvent)
  • mozilla::InternalFocusEvent (旧nsFocusEvent)
  • mozilla::InternalTransitionEvent (旧nsTransitionEvent)
  • mozilla::InternalAnimationEvent (旧nsAnimationEvent)
mozilla/MiscEvents.h
  • mozilla::WidgetContentCommandEvent (旧nsContentCommandEvent)
  • mozilla::WidgetCommandEvent (旧nsCommandEvent)
  • mozilla::WidgetPluginEvent (旧nsPluginEvent)
mozilla/MouseEvents.h
  • enum nsDragDropEventStatus
  • mozilla::WidgetMouseEventBase (旧nsMouseEvent_base)
  • mozilla::WidgetMouseEvent (旧nsMouseEvent)
  • mozilla::WidgetDragEvent (旧nsDragEvent)
  • mozilla::WidgetMouseScrollEvent (旧nsMouseScrollEvent)
  • mozilla::WidgetWheelEvent (旧mozilla::WheelEvent)
mozilla/TextEvents.h
  • NS_VK_*
  • mozilla::AlternativeCharCode (旧nsAlternativeCharCode)
  • mozilla::WidgetKeyboardEvent (旧nsKeyEvent)
  • mozilla::TextRangeStyle (旧nsTextRangeStyle)
  • mozilla::TextRange (旧nsTextRange)
  • mozilla::TextRangeArray (旧nsTextRangeArray)
  • mozilla::WidgetTextEvent (旧nsTextEvent)
  • mozilla::WidgetCompositionEvent (旧nsCompositionEvent)
  • mozilla::WidgetQueryContentEvent (旧nsQueryContentEvent)
  • mozilla::WidgetSelectionEvent (旧nsSelectionEvent)
mozilla/TouchEvents.h
  • mozilla::WidgetGestureNotifyEvent (旧nsGestureNotifyEvent)
  • mozilla::WidgetSimpleGestureEvent (旧nsSimpleGestureEvent)
  • mozilla::WidgetTouchEvent (旧nsTouchEvent)
mozilla/MutationEvent.h
  • mozilla::InternalMutationEvent (旧nsMutationEvent)
  • NS_EVENT_BITS_MUTATION_*

ネイティブイベントをGeckoに伝達するために、widgetが使用するイベントは、Widget prefix付きで、それ以外、DOMイベントの実データの保存領域として使われるものは、Internal prefix付きのクラス名になっています。

このバグの修正時には、全ての旧クラス名や、旧構造体名はそのまま利用できるようにtypedefで別名を宣言してありますが、Bug-org 920377で順次、この別名を削除して、新しい名前を使用するように置換作業を行っています。

また、大量にあったマクロやインライン関数のイベントに関するユーティリティ類は、全て、WidgetEventのメソッドとして実装し、widget/shared/WidgetEventImpl.cppで実装しています。今後、さらに有用なメソッドを追加しても、その実装によって依存関係が増えない形になりましたので、より、イベント周りのコードは整理されていくと思います。

また、最後にnsGUIEvent.hは削除され、新しいヘッダファイルは必要なものだけを直接、インクルードするように修正しています。BasicEvents.hを変更した場合のリビルド対象はまだまだ多いですが、この辺も、別のバグで対応していく予定です。