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イベントを生成するようにしました。
色々と細かい話があったはずなのですが、半年前に書いて、塩漬けになっていたパッチですので、細かいことは忘れてしまいました……