Bug-org 630813 Store the native modifier mask information in GdkKeymap's wrapper class and use it instead of GDK_MOD*_MASK
初回投稿日時: 2012年02月23日11時04分14秒
最終更新日時: 2012年02月23日11時06分06秒
カテゴリ: Mozilla Core Mozilla13 バグ修正
SNS:
Tweet (list)
1年もかかってしまいましたが、ようやく大物がひとつ片付きました。Linuxのキーイベントの処理のうちのややこしい部分をnsWindow
から分離しました。GtkKeymap
のラッパーで、名前もそのままに、mozilla::widget::KeymapWrapper
です。
GDKでは、正体がよく分かってませんが、GdkDisplay
単位でGdkKeymap
を管理することができます。一応設計としては、そのような複数のGdkDisplay
が存在する環境が当たり前になった場合にも対応できるようにはしていますが、今回の修正では簡略化のためにデフォルトのGdkDisplay
のGdkKeymap
に常にアクセスするようにしています(これは既存の動作のまま)。ですので、もし、この挙動で困る環境があって、修正すべきだと考えられるのであれば、バグを報告してもらって、利用シーンについて説明してもらえれれば対応可能だと思います。
話がそれてしまいましたので戻します。今回の修正では主に、モディファイアキーの処理の改善を目的においていました。Xにおいて、モディファイアの定義というのは抽象化されすぎていて、GDKでは以下のような定数で定義されています。
typedef enum { GDK_SHIFT_MASK = 1 << 0, GDK_LOCK_MASK = 1 << 1, GDK_CONTROL_MASK = 1 << 2, GDK_MOD1_MASK = 1 << 3, GDK_MOD2_MASK = 1 << 4, GDK_MOD3_MASK = 1 << 5, GDK_MOD4_MASK = 1 << 6, GDK_MOD5_MASK = 1 << 7, GDK_BUTTON1_MASK = 1 << 8, GDK_BUTTON2_MASK = 1 << 9, GDK_BUTTON3_MASK = 1 << 10, GDK_BUTTON4_MASK = 1 << 11, GDK_BUTTON5_MASK = 1 << 12, /* The next few modifiers are used by XKB, so we skip to the end. * Bits 15 - 25 are currently unused. Bit 29 is used internally. */ GDK_SUPER_MASK = 1 << 26, GDK_HYPER_MASK = 1 << 27, GDK_META_MASK = 1 << 28, GDK_RELEASE_MASK = 1 << 30, GDK_MODIFIER_MASK = 0x5c001fff } GdkModifierType;
GDK_MOD1_MASK
が慣例的にAltとなっていますが、NumLockに関しては定義されていません。
さらに悩ましいことに、他のプラットフォームと違って、モディファイアとモディファイアキーが1対1の関係にはなく、ひとつの物理キーが複数のモディファイアの意味を持つことがあります。例えば、一般的なディストリビューションをインストールして、特にキーボードレイアウトを変更しないまま利用していると、Altキーは、Alt
にあたるモディファイアの状態を変更しますが、Alt+Shiftだと、モディファイアの状態変更はそのままに、Metaキーが押されたというイベントに変わってしまいます。このままでは他のプラットフォームでの挙動と整合性がとれません。
今回の修正の一点目は、各物理キーが、どのモディファイアのビットを含んでいるのかを予め取得しておき、これをDOMキーイベントの挙動補正に利用するようになりました。以前説明したように、Linuxではアプリケーションがキーイベントを処理している段階では、モディファイアの状態はまだ変更されていませんので、モディファイアキーのkeydown
イベントを送信する際には、その押されたキーのもつモディファイアも含めて反映するようになりました。keyup
イベント時のモディファイア情報は今まで変わらず補正無しで、他のプラットフォームとは異なり、モディファイアの状態は実際には押されてなくても、DOMキーイベントでは押されたままとなっています。
二点目は、モディファイアキーのDOMキーイベントのkeyCode
は他のモディファイアキーが押されていない状態でのキーを基に、算出されるようになりました。上記のように、Shift+Altで、DOM_VK_METAキーとなっていた環境でも、Altキーのみを押した場合と同様にDOM_VK_ALTキーがkeyCode
に設定されるようになりました。ただし、他のモディファイアキーとの組み合わせで初めてモディファイアキーになるような場合、例えば、JISキーボードレイアウトでは、標準設定のままだと、Shift+英数でCapsLockキーになります。このような場合に、keyCode
を英数キーのものにしてしまうと問題がありますので、CapsLockキーのkeyCode
をそのまま送信します。
三点目は、全てのモディファイアキーを調べられるDOMイベントではこの新しいクラスでisShift
、isControl
、isAlt
、isMeta
を設定されるようになりました。これに伴い、isMeta
の値がイベントの種類によってまちまちだった状況が改善され、常にfalse
になっています。Metaという名前が悪いと思うのですが、これはMacではショートカットキーのコンビネーションで主に利用されるCommandキーが押された場合にtrue
になりますので、Mac版でのみテストされたWebアプリケーションでは誤動作する可能性がありました。また、Macのこのキーは明らかにLinuxでのMetaキーとは異なっています。他のプラットフォームには存在せず、また重要ではないモディファイアがWebアプリから簡単に利用できても有害なのでこの情報はDOMイベントには反映されなくなりました。
今回の修正で最も大きな成果は、アクティブなキーボードレイアウトの生存期間のみ生存しているインスタンスができたことです。これにより、今まではパフォーマンスを気にして細かく調べられなかったことを調べ、その結果をキャッシュしておくことが可能になりました。また、単純にnsWindow
からの独立は機能を拡張しやすくなったことを意味しています。来週以降、このバグ待ちで止まっていたWindows、Mac、LinuxでのkeyCode
算出ルールの統一化の作業を行っていきます。Webコンテンツ的には本来なら必要の無い話なのですが、keyCode
はchrome内のスクリプトにとっては変わらず重要な情報ですのでここを避けて通ることはできません。ですが、これが終わればいよいよこれらのプラットフォームで同時にD3EのKeyboardEvent
の各属性を順番に実装していく予定です。順調にいけば、来年リリースされる分ぐらいからは、FirefoxのキーボードイベントはD3E仕様をほぼ満たしたものになるのではないかと思います。