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

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

もずはっく日記(2012年7月)

2012年7月26日

Bug-org 751749 cannot configure keyboard shortcuts to use Meta modifier instead of Alt
初回投稿日時: 2012年07月26日09時37分18秒
最終更新日時: 2012年07月26日09時56分11秒
カテゴリ: GTK Mozilla Core Mozilla17 バグ修正
SNS: (list)

Bug-org 630813によるregressionです。

Bug-org 630813では、Linuxでは現在、Meta一般的ではないので、DOM KeyboardEventからは、Metaキーのイベントを参照できるべきではないとの判断で、押されたキーが、モディファイアキー無しで押された場合に、そのキーがGDK_Meta_(L|R)を生成する場合であっても、DOM_VK_METAを生成しないようにし、さらに、KeyboardEvent.metaKeytrueを返さないように修正を行いました。

しかし、実際にBug-org 630813が入ったビルド(Fx13)がリリースされると、一部、特殊なキーボードを利用しているユーザを中心にバグ報告がありました。その内容は、Sunや、MacのキーボードをLinuxで利用した場合、従来まではDOMイベントで、Metaキーとして扱われていたもの(つまり、そのキーと一緒に押したキーのイベントで、metaKeytrueとなるモディファイアキー)が、モディファイアキーとして機能しなくなったというもので、この現象自体がこのバグの修正対象です。

Bug-org 630813の修正内容を理解しなければ、このバグの理由、修正方法が理解できないので、再度説明しておきます。

Bug-org 630813で問題としたのは、ネイティブのモディファイアフラグと、DOMのモディファイアとの関係が、そのモディファイアフラグをアクティブにするキーとの関係と一致していない事でした。

Linuxのツールキット、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では、SuperHyperMetaについても定義があるのですが、新しいものですので、現在のGeckoでは無視しています。

それを踏まえてこのenumを見てみると、ShiftCapsLockCtrlキー以外のモディファイアに対するモディファイアフラグは、1から5が用意されているだけです。現に、GDK_Alt_(L|R)GDK_Meta_(L|R)GDK_Super_(L|R)GDK_Hyper_(L|R)GDK_Num_LockGDK_Scroll_Lockを生成するキーと、モディファイアフラグとの関係性は一定ではありません。極端な話、UbuntuやFedoraに付属しているキーボードレイアウトの設定から、設定をいじるだけで関係がずれてしまいます。

そこで、Geckoは、DOM Level3 EventsのKeyboardEventに対応するため、XのAPIを利用して、各フラグをアクティブにする物理キーが生成するGDKのkeyval値(上の例だと、GDK_Alt_L等)から各フラグがアクティブにする、DOMのモディファイアとの関係を初期化時に決定することにしました。

そのロジックは、基本的には、モディファイアフラグをアクティブにするキーが生成する可能性のある全てのkeyval値に対応する、DOMのモディファイアを同時にアクティブにするというもので、さらに、GDK_Meta_(L|R)は、DOMのMetaはアクティブにしないという(今、考えてみると)バグも混入されました。

ちなみに、それ以前は、MOD1が、AltMOD5が、Metaキーであるという慣例に従って、決め打ちを行っていました。

この事実と、前述の修正内容の結果、MOD5をアクティブにするキーが単独で押された場合に生成されるkeyvalGDK_Meta_(L|R)GDK_Super_(L|R)GDK_Hyper_(L|R)だった場合に、そのキーがショートカットキーや、アクセスキーのためのモディファイアキーとして機能しなくなってしまっていました(SuperHyperWinキーとして読み替えられ、osモディファイアだと扱われますが、osモディファイア自体が、ショートカットキーや、アクセスキーのモディファイアとして利用ができないため、Metaキー以外の場合にも影響が出ました)。

この問題を修正するために、このバグでは以下のアプローチをとりました。

  • DOMのMetaキーを復活
  • XULの<key>要素は簡単に指定すると、全てのモディファイアの状態がマッチしていないと動作しないので、ひとつのモディファイアフラグが、ひとつのDOMモディファイアしかアクティブにしないように修正
  • MOD5をアクティブにしていたキーが、Super、もしくはHyperの場合にも、ショートカットキーや、アクセスキーのモディファイアキーとして利用できるようにXULの<key>要素のmodifiers属性で、osを指定できるように修正

このような修正ですので、このバグで困っていた人は、ui.key.accelKeyの設定を変えなくては依然として、期待通りに利用できない可能性があります。

ui.key.accelKeyの値は新たに、DOM_VK_WINを意味する、91が指定可能になりました。

ui.key.chromeAccessと、ui.key.contentAccessは、16をOR演算で含めることができるようになりました。

関連するかもしれないエントリ

bug-org 751749を含むエントリ