2014年12月31日
Windows向けのユーティリティソフト、PlainTextを利用して、クリップボードの内容をHTMLとしてではなく、プレーンテキストとして貼り付けようとしても、貼り付け自体が動かないというバグです。
Spy++で挙動を確認してみると、このアプリは、Win + Vが押された時に、クリップボードの内容をプレーンテキストのみに変更した後、Ctrl + Vをエミュレーションして、アプリの貼り付けを強引に動かしているようです。しかし、Win + Vが押された時に、同期的に処理しているため、Winキーが押されたままなので、Win + Ctrl + Vが生成されていました。
WindowsとLinux GTKのネイティブアプリの挙動を確認してみると、GTKアプリでは、Win (Super)キーの状態を確認していて、Win + Ctrl + Vで貼り付けは動作しませんでしたが、WindowsではWinキーの状態を無視しているようで、Win + Ctrl + Vでも、Ctrl + Vが実行されました。Geckoでは、ショートカットキーは一般的に以下のような定義になっています。
<key key="v" modifiers="control"/>
これは、GTKのネイティブアプリと同じ動作となります。つまり、Ctrlキー以外のモディファイアキーはオフであることを条件としています。
これに対し、Windowsのネイティブアプリと同様の動作を実現するためには、以下のように記述しなくていけません。
<key key="v" modifiers="os any control"/>
any
キーワードよりも前に列挙されたモディファイアの状態を問わないということを意味しますので、Win + Ctrl + Vでも、Ctrl + Vでもマッチするようになります。
しかし、全てのショートカットキーをWindowsでのみ、このように書き換えていく訳にはいきません。そこで、そこで、Windowsでのみ、XULの<key>
要素の動作を変更することにしました。
新しい動作では、まず、従来と同様に(つまり、他のOS上で動作している時と同様に)、ショートカットキーのマッチングを行います。そして、マッチする<key>
要素が発見できず、なおかつ、Winキーが押されている場合、Winキーを無視してマッチングを行います。実例を挙げると、以下のような宣言があるとします。
<key key="v" modifiers="control"/>
<key key="v" modifiers="os control"/>
この場合、Winキーが押されている場合は、二つ目にマッチします。なぜなら、一回目のマッチングでは、Winキーの状態を無視しないからです。ですので、このような場合にはこのバグでの修正は良い意味で変化がないことになります。
D3EのKeyboardEvent.key
の値を最新の仕様案にあわせて更新しようというバグです。まだ、一部のキー名についてはワーキンググループに確認をとっているところで、本来はこれが終わってから全ての修正を一度に行う予定でしたが、約半年、ワーキンググループから回答が来ていないので、安定している部分に関してのみ、修正を先行させることにしました。
今回、このバグ名義での修正は、キーの名前の変更を予告していたワーニングメッセージの削除のみを行っています(Bug-org 1024864のバックアウト)。
最新のD3E仕様にあわせて、Menu
キーは、ContextMenu
キーにリネームしました。
最新のD3E仕様にあわせて、Crsel
は、CrSel
に、Exsel
は、ExSel
に変更しました。
最新のD3E仕様にあわせて、矢印キーの名前をLeft
はArrowLeft
に、Right
はArrowRight
に、Up
はArrowUp
に、Down
はArrowDown
に変更しました。
最新のD3E仕様にあわせて、Del
はDelete
に、Esc
はEscape
に変更しました。
最新のD3E仕様にあわせて、Zoom
をZoomToggle
に変更しました。
最新のD3E仕様にあわせて、MediaNextTrack
をMediaTrackNext
に、MediaPreviousTrack
をMediaTrackPrevious
に、SelectMedia
をMediaSelect
に変更しました。
最新のD3E仕様にあわせて、リモコンで見かけるカラーキーの名前を、Red
をColorF0Red
に、Green
をColorF1Green
に、Yellow
をColorF2Yellow
に、Blue
をColorF3Blue
に変更しました。
余談ですが、テレビ等のカラーボタンの配列は、日本と欧米(?)では異なっているので、青、赤、緑、黄の順で数字が上がっていっていないので注意してください。
最新のD3E仕様にあわせて、Apps
をMediaApps
に、FastFwd
をMediaFastForward
に変更しました。
この修正により、AndroidのKEYCODE_APP_SWITCH
キーは、Unidentified
になっていますので注意してください。
最新のD3E仕様では、Macの日本語キーボードにある英数キー用にEisu
が定義されました。そこで、RomanCharacters
から、Eisu
にマッピングを変更しています。
また、AndroidとFirefox OSも今回、Macと同様にマッピングを行っています。
最新のD3E仕様では、日本語環境固有のキーにはラベルに即した名前が再定義されました。これにより、Nonconvert
をNonConvert
に、HalfWidth
はHankaku
に、FullWidth
はZenkaku
に、RomanCharacters
はRomaji
に変更しました。
以前のD3E仕様案では、デッドキーは、入力されるであろう文字ごとに名前が定義されていましたが、その数が膨大になっていく問題と、一部のプラットフォームでは、ネイティブイベントが示す、非合成文字から、合成文字を推測し、キー名にマッピングしなくてはいけないので、ブラウザ間での互換性の維持が困難という問題がありました。そのため、全てのデッドキーは、Dead
というkey
値で表現されるようになりました。
最新のD3E仕様では、Live
キーが、LiveContent
に変更になりました。また、これまでGeckoは、AndroidのKEYCODE_TV
をこれにマッピングしていましたが、それはおかしい、意図していない使い方であると、D3Eのワーキンググループから指摘されたので、このマッピングを廃止しています。
Geckoは、LiveContent
をどのプラットフォームのどのキーにもマッピングしていません。
最新のD3E仕様では、新たに、ZoomIn
キー、ZoomOut
キーが定義されたので、GTK、Qt、Android、Firefox OSでは該当するキーコードをこれらにマッピングしました。
最新のD3E仕様では、新たに、Standby
、PowerOff
、WakeUp
、LogOff
、Suspend
、Hibernate
キーが定義されました。これにあわせて、GTK、Qt、Windowsでは該当するキーにマッピングしました。
D3E仕様には、Undo
キーはありましたが、Redo
キーがありませんでした。しかし、GTKでは定義されているため、新たに定義されました。このバグでは、簡単にマッピングが可能なGTKでのみ、マッピングを行っています。
GTKとQtでは、IBMのAIXの韓国語IME用に、単一候補を変換するキーが定義されていました。これに対応するため、D3Eの最新仕様ではSingleCandidate
キーを定義し、Geckoは、各キーコードをこれにマッピングしています。
Linux、Android系のプラットフォームでは、半角/全角キーや、カタカナ/ひらがなキーが、同じキーコードでキーイベントを生成するため、アプリ側は、イベントからはどちらのモードへの切り替えが行われているのか判別できません。これに対応するため、最新のD3E仕様では、不明な場合に物理的なキーの判別を手軽に行えるように、ZenkakuHankaku
キーと、HiraganaKatakana
キーの二つを定義しました。Webアプリがこれらのキーを直接ハンドリングすることはほとんど無いと思いますが、これらのキーを処理する場合、Windows版Geckoでは、Zenkaku
、Hankaku
、Hiragana
、Katakana
キーになっていることに注意してください。
GTKでは、キーボードレイアウトを変更するキーのキーコードが定義されています。また、Androidでも、KEYCODE_LANGUAGE_SWITCH
というキーが定義されています。これにあわせて、最新のD3E仕様では、GroupNext
、GroupPrevious
、GroupFirst
、GroupLast
キーが定義され、Geckoはこれらをマッピングしました。ちなみに、Android・Firefox OSのKEYCODE_LANGUAGE_SWITCH
は、GroupNext
にマッピングしています。
Androidでは、マルチメディアプレーヤーの、リモコン用のキーが定義されています。これを表現するために、最新のD3E仕様では、TV
、TVInput
、TVPower
、AVInput
、AVPower
、STBInput
、STBPwer
が定義されました。Geckoでは単純に、該当するキーにマッピングを行いました。
Linux系と、Android系のプラットフォームでは、特定のアプリを起動するキーが多数定義されています。これにあわせて、D3E最新仕様では、Launch
というプリフィックスの後ろに、アプリ名を入れることで、キー名をブラウザベンダが定義できるようにしています。今回の修正では、Webアプリにとって、さほど重要なキーではないことから、仕様でサンプルとして定義しているキーのみを追加し、マッピングしています。
Microsoft社が出した、マルチメディアキーボードには、メーラーを操作するキーや、新規ドキュメント作成等の編集作業に便利なキーがありますが、GTKやQtでは、これらのキーのキーコードも定義しています。そこで、これらに対応するため、最新のD3E仕様では、Close
、MailForward
、MailReply
、MailSend
、New
、Open
、Print
、Save
、SpellCheck
キーが定義されました。GeckoではGTK、Qt上ではシンプルにこれらのキーをマッピングしています。
Androidでは、KEYCODE_SYM
というキーコードで、Symbolというモディファイアキーが定義されています。何に使用されているキーかは不明ですが、これを表現するために、D3Eの最新仕様ではSymbol
キーが定義されました。Geckoではこれを単純にマッピングしています。
最新のD3E仕様で定義されたキーの中に、VideoModeNext
というキーがあります。これは、仕様書で参照している仕様で定義されているものですが、GTKに名前が同じ意味になるものが、存在していたので、Geckoではひとまず、マッピングを行いました。
スマホには、ホームスクリーンへ戻る、Homeボタンが存在しています。これは、全てのアプリから戻るということで、Exit
を割り当てていましたが、そのマッピングはおかしいと、D3Eのワーキンググループから指摘があったので、このマッピングを廃止しています。
ちなみに、Webブラウザでは、スマホのホームボタンはキーイベントすら発生しませんので、この修正による影響はFirefox OSのGaia等に限定された話となります。
最新のD3E仕様には、MediaFastForward
というキーが定義されていますが、GTKのGDK_AudioForward
がこれに適切ではないか、ということで、新たにマッピングを追加しています。
Windowsでは、マルチメディアキーボードの、メール関連のキーや、編集関連のキー等が押された場合に、通常のWM_KEYDOWN
メッセージではなく、WM_APPCOMMAND
というメッセージがアプリに送信されます。Geckoはこれを受け取ると、内部向けのコマンドイベントを生成し、処理していますが、WM_APPCOMMAND
は、その原因がキー操作かそれ以外かが分かるようになっていますので、D3Eで定義されたキーであれば、最初にkeydown
イベントを生成し、これがpreventDefault()
で、デフォルトアクションをキャンセルされていなければ、従来通り、内部向けのコマンドイベントを生成し、最後に、keyup
イベントを生成するようにしました。
色々と細かい話があったはずなのですが、半年前に書いて、塩漬けになっていたパッチですので、細かいことは忘れてしまいました……