Bug 1833494 - Make GlobalKeyListener not try to match handler with keyboard event with ignoring Shift state after one handler matches with the key combination r=smaug

`GlobalKeyListener` try to match shortcut keys with exactly checking `Shift`
state, but for the cases which do not match localized language and active
keyboard layout location, it scans another shortcut keys with ignoring
`Shift` state if no handler is available.

`<command>` elements and `<key>` elements may be disabled conditionally.
E.g., Zoom-in/Zoom-out are disabled when current zoom level is max/min value.
In this case, it's odd that another shortcut key which does not exactly match
the modifiers works.

Therefore, this patch makes `GlobalKeyListener` does not try to scan handlers
with ignoring `Shift` state if it has already found a disabled handler which
exactly matches with the modifiers.

Differential Revision: https://phabricator.services.mozilla.com/D184789
This commit is contained in:
Masayuki Nakano 2023-08-09 04:47:06 +00:00
parent fc74f60e4b
commit e6f42bf7f7
12 changed files with 655 additions and 91 deletions

View file

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GlobalKeyListener.h"
#include "ErrorList.h"
#include "EventTarget.h"
#include <utility>
@ -104,7 +105,7 @@ void GlobalKeyListener::WalkHandlers(dom::KeyboardEvent* aKeyEvent) {
return;
}
WalkHandlersInternal(aKeyEvent, true);
WalkHandlersInternal(Purpose::ExecuteCommand, aKeyEvent);
}
void GlobalKeyListener::InstallKeyboardEventListenersTo(
@ -202,8 +203,7 @@ void GlobalKeyListener::HandleEventOnCaptureInDefaultEventGroup(
return;
}
bool isReserved = false;
if (HasHandlerForEvent(aEvent, &isReserved) && isReserved) {
if (HasHandlerForEvent(aEvent).mReservedHandlerForChromeFound) {
widgetKeyboardEvent->MarkAsReservedByChrome();
}
}
@ -223,7 +223,7 @@ void GlobalKeyListener::HandleEventOnCaptureInSystemEventGroup(
return;
}
if (!HasHandlerForEvent(aEvent)) {
if (!HasHandlerForEvent(aEvent).mMeaningfulHandlerFound) {
return;
}
@ -242,13 +242,12 @@ void GlobalKeyListener::HandleEventOnCaptureInSystemEventGroup(
// WalkHandlersInternal and WalkHandlersAndExecute
//
// Given a particular DOM event and a pointer to the first handler in the list,
// scan through the list to find something to handle the event. If aExecute =
// true, the handler will be executed; otherwise just return an answer telling
// if a handler for that event was found.
// scan through the list to find something to handle the event. If aPurpose =
// Purpose::ExecuteHandler, the handler will be executed; otherwise just return
// an answer telling if a handler for that event was found.
//
bool GlobalKeyListener::WalkHandlersInternal(dom::KeyboardEvent* aKeyEvent,
bool aExecute,
bool* aOutReservedForChrome) {
GlobalKeyListener::WalkHandlersResult GlobalKeyListener::WalkHandlersInternal(
Purpose aPurpose, dom::KeyboardEvent* aKeyEvent) {
WidgetKeyboardEvent* nativeKeyboardEvent =
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
MOZ_ASSERT(nativeKeyboardEvent);
@ -257,49 +256,62 @@ bool GlobalKeyListener::WalkHandlersInternal(dom::KeyboardEvent* aKeyEvent,
nativeKeyboardEvent->GetShortcutKeyCandidates(shortcutKeys);
if (shortcutKeys.IsEmpty()) {
return WalkHandlersAndExecute(aKeyEvent, 0, IgnoreModifierState(), aExecute,
aOutReservedForChrome);
return WalkHandlersAndExecute(aPurpose, aKeyEvent, 0,
IgnoreModifierState());
}
for (unsigned long i = 0; i < shortcutKeys.Length(); ++i) {
ShortcutKeyCandidate& key = shortcutKeys[i];
bool foundDisabledHandler = false;
for (const ShortcutKeyCandidate& key : shortcutKeys) {
const bool skipIfEarlierHandlerDisabled =
key.mSkipIfEarlierHandlerDisabled ==
ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled::Yes;
if (foundDisabledHandler && skipIfEarlierHandlerDisabled) {
continue;
}
IgnoreModifierState ignoreModifierState;
ignoreModifierState.mShift = key.mIgnoreShift;
if (WalkHandlersAndExecute(aKeyEvent, key.mCharCode, ignoreModifierState,
aExecute, aOutReservedForChrome)) {
return true;
ignoreModifierState.mShift =
key.mShiftState == ShortcutKeyCandidate::ShiftState::Ignorable;
WalkHandlersResult result = WalkHandlersAndExecute(
aPurpose, aKeyEvent, key.mCharCode, ignoreModifierState);
if (result.mMeaningfulHandlerFound) {
return result;
}
// Note that if the candidate should not match if an earlier handler is
// disabled, the char code of the candidate is a char which may be
// introduced with different shift state. In this case, we do NOT find a
// disabled handler which **exactly** matches with the keyboard event.
// This avoids to override a higher priority handler with a disabled lower
// priority handler.
if (!skipIfEarlierHandlerDisabled && !foundDisabledHandler) {
foundDisabledHandler = result.mDisabledHandlerFound;
}
}
return false;
return {};
}
bool GlobalKeyListener::WalkHandlersAndExecute(
dom::KeyboardEvent* aKeyEvent, uint32_t aCharCode,
const IgnoreModifierState& aIgnoreModifierState, bool aExecute,
bool* aOutReservedForChrome) {
if (aOutReservedForChrome) {
*aOutReservedForChrome = false;
}
GlobalKeyListener::WalkHandlersResult GlobalKeyListener::WalkHandlersAndExecute(
Purpose aPurpose, dom::KeyboardEvent* aKeyEvent, uint32_t aCharCode,
const IgnoreModifierState& aIgnoreModifierState) {
WidgetKeyboardEvent* widgetKeyboardEvent =
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
if (NS_WARN_IF(!widgetKeyboardEvent)) {
return false;
return {};
}
nsAtom* eventType =
ShortcutKeys::ConvertEventToDOMEventType(widgetKeyboardEvent);
// Try all of the handlers until we find one that matches the event.
bool foundDisabledHandler = false;
for (KeyEventHandler* handler = mHandler; handler;
handler = handler->GetNextHandler()) {
bool stopped = aKeyEvent->IsDispatchStopped();
if (stopped) {
// The event is finished, don't execute any more handlers
return false;
return {};
}
if (aExecute) {
if (aPurpose == Purpose::ExecuteCommand) {
if (!handler->EventTypeEquals(eventType)) {
continue;
}
@ -329,17 +341,18 @@ bool GlobalKeyListener::WalkHandlersAndExecute(
// Before executing this handler, check that it's not disabled,
// and that it has something to do (oncommand of the <key> or its
// <command> is non-empty).
if (!CanHandle(handler, aExecute)) {
if (!CanHandle(handler, aPurpose == Purpose::ExecuteCommand)) {
foundDisabledHandler = true;
continue;
}
if (!aExecute) {
if (aPurpose == Purpose::LookForCommand) {
if (handler->EventTypeEquals(eventType)) {
if (aOutReservedForChrome) {
*aOutReservedForChrome = IsReservedKey(widgetKeyboardEvent, handler);
}
return true;
WalkHandlersResult result;
result.mMeaningfulHandlerFound = true;
result.mReservedHandlerForChromeFound =
IsReservedKey(widgetKeyboardEvent, handler);
return result;
}
// If the command is reserved and the event is keydown, check also if
@ -348,27 +361,28 @@ bool GlobalKeyListener::WalkHandlersAndExecute(
if (eventType == nsGkAtoms::keydown &&
handler->EventTypeEquals(nsGkAtoms::keypress)) {
if (IsReservedKey(widgetKeyboardEvent, handler)) {
if (aOutReservedForChrome) {
*aOutReservedForChrome = true;
}
return true;
WalkHandlersResult result;
result.mMeaningfulHandlerFound = true;
result.mReservedHandlerForChromeFound = true;
return result;
}
}
// Otherwise, we've not found a handler for the event yet.
continue;
}
// This should only be assigned when aExecute is false.
MOZ_ASSERT(!aOutReservedForChrome);
nsCOMPtr<dom::EventTarget> target = GetHandlerTarget(handler);
// XXX Do we execute only one handler even if the handler neither stops
// propagation nor prevents default of the event?
nsresult rv = handler->ExecuteHandler(target, aKeyEvent);
if (NS_SUCCEEDED(rv)) {
return true;
WalkHandlersResult result;
result.mMeaningfulHandlerFound = true;
result.mReservedHandlerForChromeFound =
IsReservedKey(widgetKeyboardEvent, handler);
result.mDisabledHandlerFound = (rv == NS_SUCCESS_DOM_NO_OPERATION);
return result;
}
}
@ -380,12 +394,14 @@ bool GlobalKeyListener::WalkHandlersAndExecute(
if (!aIgnoreModifierState.mMeta && widgetKeyboardEvent->IsMeta()) {
IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
ignoreModifierState.mMeta = true;
return WalkHandlersAndExecute(aKeyEvent, aCharCode, ignoreModifierState,
aExecute);
return WalkHandlersAndExecute(aPurpose, aKeyEvent, aCharCode,
ignoreModifierState);
}
#endif
return false;
WalkHandlersResult result;
result.mDisabledHandlerFound = foundDisabledHandler;
return result;
}
bool GlobalKeyListener::IsReservedKey(WidgetKeyboardEvent* aKeyEvent,
@ -420,21 +436,21 @@ bool GlobalKeyListener::IsReservedKey(WidgetKeyboardEvent* aKeyEvent,
.IsEmpty();
}
bool GlobalKeyListener::HasHandlerForEvent(dom::KeyboardEvent* aEvent,
bool* aOutReservedForChrome) {
GlobalKeyListener::WalkHandlersResult GlobalKeyListener::HasHandlerForEvent(
dom::KeyboardEvent* aEvent) {
WidgetKeyboardEvent* widgetKeyboardEvent =
aEvent->WidgetEventPtr()->AsKeyboardEvent();
if (NS_WARN_IF(!widgetKeyboardEvent) || !widgetKeyboardEvent->IsTrusted()) {
return false;
return {};
}
EnsureHandlers();
if (IsDisabled()) {
return false;
return {};
}
return WalkHandlersInternal(aEvent, false, aOutReservedForChrome);
return WalkHandlersInternal(Purpose::LookForCommand, aEvent);
}
//

View file

@ -56,18 +56,31 @@ class GlobalKeyListener : public nsIDOMEventListener {
MOZ_CAN_RUN_SCRIPT
void WalkHandlers(dom::KeyboardEvent* aKeyEvent);
enum class Purpose {
ExecuteCommand,
LookForCommand,
};
struct MOZ_STACK_CLASS WalkHandlersResult {
// Set to true if it found a command matches with given keyboard event and
// it's available.
bool mMeaningfulHandlerFound = false;
// Set to true if the command which is found or executed is reserved for
// chrome.
bool mReservedHandlerForChromeFound = false;
// Set to true if found handler is disabled.
bool mDisabledHandlerFound = false;
};
// walk the handlers, looking for one to handle the event
MOZ_CAN_RUN_SCRIPT
bool WalkHandlersInternal(dom::KeyboardEvent* aKeyEvent, bool aExecute,
bool* aOutReservedForChrome = nullptr);
WalkHandlersResult WalkHandlersInternal(Purpose aPurpose,
dom::KeyboardEvent* aKeyEvent);
// walk the handlers for aEvent, aCharCode and aIgnoreModifierState. Execute
// it if aExecute = true.
// Walk the handlers for aEvent, aCharCode and aIgnoreModifierState.
MOZ_CAN_RUN_SCRIPT
bool WalkHandlersAndExecute(dom::KeyboardEvent* aKeyEvent, uint32_t aCharCode,
const IgnoreModifierState& aIgnoreModifierState,
bool aExecute,
bool* aOutReservedForChrome = nullptr);
WalkHandlersResult WalkHandlersAndExecute(
Purpose aPurpose, dom::KeyboardEvent* aKeyEvent, uint32_t aCharCode,
const IgnoreModifierState& aIgnoreModifierState);
// HandleEvent function for the capturing phase in the default event group.
MOZ_CAN_RUN_SCRIPT
@ -80,8 +93,7 @@ class GlobalKeyListener : public nsIDOMEventListener {
// whether the command handler for the event is marked with the "reserved"
// attribute.
MOZ_CAN_RUN_SCRIPT
bool HasHandlerForEvent(dom::KeyboardEvent* aEvent,
bool* aOutReservedForChrome = nullptr);
WalkHandlersResult HasHandlerForEvent(dom::KeyboardEvent* aEvent);
// Returns true if the key would be reserved for the given handler. A reserved
// key is not sent to a content process or single-process equivalent.

View file

@ -6,6 +6,7 @@
#include "mozilla/ArrayUtils.h"
#include "ErrorList.h"
#include "nsCOMPtr.h"
#include "nsQueryObject.h"
#include "KeyEventHandler.h"
@ -319,7 +320,7 @@ nsresult KeyEventHandler::DispatchXULKeyCommand(dom::Event* aEvent) {
if (handlerElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
nsGkAtoms::_true, eCaseMatters)) {
// Don't dispatch command events for disabled keys.
return NS_OK;
return NS_SUCCESS_DOM_NO_OPERATION;
}
aEvent->PreventDefault();

View file

@ -131,9 +131,10 @@ Maybe<KeyboardShortcut> KeyboardMap::FindMatch(
}
// Otherwise do a search with each shortcut candidate in order
for (auto& key : aEvent.mShortcutCandidates) {
for (const auto& key : aEvent.mShortcutCandidates) {
IgnoreModifierState ignoreModifierState;
ignoreModifierState.mShift = key.mIgnoreShift;
ignoreModifierState.mShift =
key.mShiftState == ShortcutKeyCandidate::ShiftState::Ignorable;
auto match = FindMatchInternal(aEvent, ignoreModifierState, key.mCharCode);
if (match) {

View file

@ -1545,102 +1545,132 @@ const KEYBOARD_LAYOUT_ARABIC = {
Win: 0x00000401,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_ARABIC", KEYBOARD_LAYOUT_ARABIC);
const KEYBOARD_LAYOUT_ARABIC_PC = {
name: "Arabic - PC",
Mac: 7,
Win: null,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_ARABIC_PC", KEYBOARD_LAYOUT_ARABIC_PC);
const KEYBOARD_LAYOUT_BRAZILIAN_ABNT = {
name: "Brazilian ABNT",
Mac: null,
Win: 0x00000416,
hasAltGrOnWin: true,
};
_defineConstant(
"KEYBOARD_LAYOUT_BRAZILIAN_ABNT",
KEYBOARD_LAYOUT_BRAZILIAN_ABNT
);
const KEYBOARD_LAYOUT_DVORAK_QWERTY = {
name: "Dvorak-QWERTY",
Mac: 4,
Win: null,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_DVORAK_QWERTY", KEYBOARD_LAYOUT_DVORAK_QWERTY);
const KEYBOARD_LAYOUT_EN_US = {
name: "US",
Mac: 0,
Win: 0x00000409,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_EN_US", KEYBOARD_LAYOUT_EN_US);
const KEYBOARD_LAYOUT_FRENCH = {
name: "French",
Mac: 8,
Mac: 8, // Some keys mapped different from PC, e.g., Digit6, Digit8, Equal, Slash and Backslash
Win: 0x0000040c,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_FRENCH", KEYBOARD_LAYOUT_FRENCH);
const KEYBOARD_LAYOUT_FRENCH_PC = {
name: "French-PC",
Mac: 13, // Compatible with Windows
Win: 0x0000040c,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_FRENCH_PC", KEYBOARD_LAYOUT_FRENCH_PC);
const KEYBOARD_LAYOUT_GREEK = {
name: "Greek",
Mac: 1,
Win: 0x00000408,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_GREEK", KEYBOARD_LAYOUT_GREEK);
const KEYBOARD_LAYOUT_GERMAN = {
name: "German",
Mac: 2,
Win: 0x00000407,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_GERMAN", KEYBOARD_LAYOUT_GERMAN);
const KEYBOARD_LAYOUT_HEBREW = {
name: "Hebrew",
Mac: 9,
Win: 0x0000040d,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_HEBREW", KEYBOARD_LAYOUT_HEBREW);
const KEYBOARD_LAYOUT_JAPANESE = {
name: "Japanese",
Mac: null,
Win: 0x00000411,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_JAPANESE", KEYBOARD_LAYOUT_JAPANESE);
const KEYBOARD_LAYOUT_KHMER = {
name: "Khmer",
Mac: null,
Win: 0x00000453,
hasAltGrOnWin: true,
}; // available on Win7 or later.
_defineConstant("KEYBOARD_LAYOUT_KHMER", KEYBOARD_LAYOUT_KHMER);
const KEYBOARD_LAYOUT_LITHUANIAN = {
name: "Lithuanian",
Mac: 10,
Win: 0x00010427,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_LITHUANIAN", KEYBOARD_LAYOUT_LITHUANIAN);
const KEYBOARD_LAYOUT_NORWEGIAN = {
name: "Norwegian",
Mac: 11,
Win: 0x00000414,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_NORWEGIAN", KEYBOARD_LAYOUT_NORWEGIAN);
const KEYBOARD_LAYOUT_RUSSIAN_MNEMONIC = {
name: "Russian - Mnemonic",
Mac: null,
Win: 0x00020419,
hasAltGrOnWin: true,
}; // available on Win8 or later.
_defineConstant(
"KEYBOARD_LAYOUT_RUSSIAN_MNEMONIC",
KEYBOARD_LAYOUT_RUSSIAN_MNEMONIC
);
const KEYBOARD_LAYOUT_SPANISH = {
name: "Spanish",
Mac: 12,
Win: 0x0000040a,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_SPANISH", KEYBOARD_LAYOUT_SPANISH);
const KEYBOARD_LAYOUT_SWEDISH = {
name: "Swedish",
Mac: 3,
Win: 0x0000041d,
hasAltGrOnWin: true,
};
_defineConstant("KEYBOARD_LAYOUT_SWEDISH", KEYBOARD_LAYOUT_SWEDISH);
const KEYBOARD_LAYOUT_THAI = {
name: "Thai",
Mac: 5,
Win: 0x0002041e,
hasAltGrOnWin: false,
};
_defineConstant("KEYBOARD_LAYOUT_THAI", KEYBOARD_LAYOUT_THAI);
/**
* synthesizeNativeKey() dispatches native key event on active window.

View file

@ -4,6 +4,14 @@
* These values are defined in each platform's SDK or documents.
*/
function _defineConstant(name, value) {
Object.defineProperty(this, name, {
value,
enumerable: true,
writable: false,
});
}
// Windows
// Windows' native key code values may include scan code value which can be
// retrieved with |((code & 0xFFFF0000 >> 16)|. If the value is 0, it will
@ -19,351 +27,696 @@
// test new regressions.
const WIN_VK_LBUTTON = 0x00000001;
_defineConstant("WIN_VK_LBUTTON", WIN_VK_LBUTTON);
const WIN_VK_RBUTTON = 0x00000002;
_defineConstant("WIN_VK_RBUTTON", WIN_VK_RBUTTON);
const WIN_VK_CANCEL = 0xe0460003;
_defineConstant("WIN_VK_CANCEL", WIN_VK_CANCEL);
const WIN_VK_MBUTTON = 0x00000004;
_defineConstant("WIN_VK_MBUTTON", WIN_VK_MBUTTON);
const WIN_VK_XBUTTON1 = 0x00000005;
_defineConstant("WIN_VK_XBUTTON1", WIN_VK_XBUTTON1);
const WIN_VK_XBUTTON2 = 0x00000006;
_defineConstant("WIN_VK_XBUTTON2", WIN_VK_XBUTTON2);
const WIN_VK_BACK = 0x000e0008;
_defineConstant("WIN_VK_BACK", WIN_VK_BACK);
const WIN_VK_TAB = 0x000f0009;
_defineConstant("WIN_VK_TAB", WIN_VK_TAB);
const WIN_VK_CLEAR = 0x004c000c;
_defineConstant("WIN_VK_CLEAR", WIN_VK_CLEAR);
const WIN_VK_RETURN = 0x001c000d;
_defineConstant("WIN_VK_RETURN", WIN_VK_RETURN);
const WIN_VK_SHIFT = 0x002a0010;
_defineConstant("WIN_VK_SHIFT", WIN_VK_SHIFT);
const WIN_VK_CONTROL = 0x001d0011;
_defineConstant("WIN_VK_CONTROL", WIN_VK_CONTROL);
const WIN_VK_MENU = 0x00380012;
_defineConstant("WIN_VK_MENU", WIN_VK_MENU);
const WIN_VK_PAUSE = 0x00450013;
_defineConstant("WIN_VK_PAUSE", WIN_VK_PAUSE);
const WIN_VK_CAPITAL = 0x003a0014;
_defineConstant("WIN_VK_CAPITAL", WIN_VK_CAPITAL);
const WIN_VK_KANA = 0x00000015;
_defineConstant("WIN_VK_KANA", WIN_VK_KANA);
const WIN_VK_HANGUEL = 0x00000015;
_defineConstant("WIN_VK_HANGUEL", WIN_VK_HANGUEL);
const WIN_VK_HANGUL = 0x00000015;
_defineConstant("WIN_VK_HANGUL", WIN_VK_HANGUL);
const WIN_VK_JUNJA = 0x00000017;
_defineConstant("WIN_VK_JUNJA", WIN_VK_JUNJA);
const WIN_VK_FINAL = 0x00000018;
_defineConstant("WIN_VK_FINAL", WIN_VK_FINAL);
const WIN_VK_HANJA = 0x00000019;
_defineConstant("WIN_VK_HANJA", WIN_VK_HANJA);
const WIN_VK_KANJI = 0x00000019;
_defineConstant("WIN_VK_KANJI", WIN_VK_KANJI);
const WIN_VK_ESCAPE = 0x0001001b;
_defineConstant("WIN_VK_ESCAPE", WIN_VK_ESCAPE);
const WIN_VK_CONVERT = 0x0000001c;
_defineConstant("WIN_VK_CONVERT", WIN_VK_CONVERT);
const WIN_VK_NONCONVERT = 0x0000001d;
_defineConstant("WIN_VK_NONCONVERT", WIN_VK_NONCONVERT);
const WIN_VK_ACCEPT = 0x0000001e;
_defineConstant("WIN_VK_ACCEPT", WIN_VK_ACCEPT);
const WIN_VK_MODECHANGE = 0x0000001f;
_defineConstant("WIN_VK_MODECHANGE", WIN_VK_MODECHANGE);
const WIN_VK_SPACE = 0x00390020;
_defineConstant("WIN_VK_SPACE", WIN_VK_SPACE);
const WIN_VK_PRIOR = 0xe0490021;
_defineConstant("WIN_VK_PRIOR", WIN_VK_PRIOR);
const WIN_VK_NEXT = 0xe0510022;
_defineConstant("WIN_VK_NEXT", WIN_VK_NEXT);
const WIN_VK_END = 0xe04f0023;
_defineConstant("WIN_VK_END", WIN_VK_END);
const WIN_VK_HOME = 0xe0470024;
_defineConstant("WIN_VK_HOME", WIN_VK_HOME);
const WIN_VK_LEFT = 0xe04b0025;
_defineConstant("WIN_VK_LEFT", WIN_VK_LEFT);
const WIN_VK_UP = 0xe0480026;
_defineConstant("WIN_VK_UP", WIN_VK_UP);
const WIN_VK_RIGHT = 0xe04d0027;
_defineConstant("WIN_VK_RIGHT", WIN_VK_RIGHT);
const WIN_VK_DOWN = 0xe0500028;
_defineConstant("WIN_VK_DOWN", WIN_VK_DOWN);
const WIN_VK_SELECT = 0x00000029;
_defineConstant("WIN_VK_SELECT", WIN_VK_SELECT);
const WIN_VK_PRINT = 0x0000002a;
_defineConstant("WIN_VK_PRINT", WIN_VK_PRINT);
const WIN_VK_EXECUTE = 0x0000002b;
_defineConstant("WIN_VK_EXECUTE", WIN_VK_EXECUTE);
const WIN_VK_SNAPSHOT = 0xe037002c;
_defineConstant("WIN_VK_SNAPSHOT", WIN_VK_SNAPSHOT);
const WIN_VK_INSERT = 0xe052002d;
_defineConstant("WIN_VK_INSERT", WIN_VK_INSERT);
const WIN_VK_DELETE = 0xe053002e;
_defineConstant("WIN_VK_DELETE", WIN_VK_DELETE);
const WIN_VK_HELP = 0x0000002f;
_defineConstant("WIN_VK_HELP", WIN_VK_HELP);
const WIN_VK_0 = 0x00000030;
_defineConstant("WIN_VK_0", WIN_VK_0);
const WIN_VK_1 = 0x00000031;
_defineConstant("WIN_VK_1", WIN_VK_1);
const WIN_VK_2 = 0x00000032;
_defineConstant("WIN_VK_2", WIN_VK_2);
const WIN_VK_3 = 0x00000033;
_defineConstant("WIN_VK_3", WIN_VK_3);
const WIN_VK_4 = 0x00000034;
_defineConstant("WIN_VK_4", WIN_VK_4);
const WIN_VK_5 = 0x00000035;
_defineConstant("WIN_VK_5", WIN_VK_5);
const WIN_VK_6 = 0x00000036;
_defineConstant("WIN_VK_6", WIN_VK_6);
const WIN_VK_7 = 0x00000037;
_defineConstant("WIN_VK_7", WIN_VK_7);
const WIN_VK_8 = 0x00000038;
_defineConstant("WIN_VK_8", WIN_VK_8);
const WIN_VK_9 = 0x00000039;
_defineConstant("WIN_VK_9", WIN_VK_9);
const WIN_VK_A = 0x00000041;
_defineConstant("WIN_VK_A", WIN_VK_A);
const WIN_VK_B = 0x00000042;
_defineConstant("WIN_VK_B", WIN_VK_B);
const WIN_VK_C = 0x00000043;
_defineConstant("WIN_VK_C", WIN_VK_C);
const WIN_VK_D = 0x00000044;
_defineConstant("WIN_VK_D", WIN_VK_D);
const WIN_VK_E = 0x00000045;
_defineConstant("WIN_VK_E", WIN_VK_E);
const WIN_VK_F = 0x00000046;
_defineConstant("WIN_VK_F", WIN_VK_F);
const WIN_VK_G = 0x00000047;
_defineConstant("WIN_VK_G", WIN_VK_G);
const WIN_VK_H = 0x00000048;
_defineConstant("WIN_VK_H", WIN_VK_H);
const WIN_VK_I = 0x00000049;
_defineConstant("WIN_VK_I", WIN_VK_I);
const WIN_VK_J = 0x0000004a;
_defineConstant("WIN_VK_J", WIN_VK_J);
const WIN_VK_K = 0x0000004b;
_defineConstant("WIN_VK_K", WIN_VK_K);
const WIN_VK_L = 0x0000004c;
_defineConstant("WIN_VK_L", WIN_VK_L);
const WIN_VK_M = 0x0000004d;
_defineConstant("WIN_VK_M", WIN_VK_M);
const WIN_VK_N = 0x0000004e;
_defineConstant("WIN_VK_N", WIN_VK_N);
const WIN_VK_O = 0x0000004f;
_defineConstant("WIN_VK_O", WIN_VK_O);
const WIN_VK_P = 0x00000050;
_defineConstant("WIN_VK_P", WIN_VK_P);
const WIN_VK_Q = 0x00000051;
_defineConstant("WIN_VK_Q", WIN_VK_Q);
const WIN_VK_R = 0x00000052;
_defineConstant("WIN_VK_R", WIN_VK_R);
const WIN_VK_S = 0x00000053;
_defineConstant("WIN_VK_S", WIN_VK_S);
const WIN_VK_T = 0x00000054;
_defineConstant("WIN_VK_T", WIN_VK_T);
const WIN_VK_U = 0x00000055;
_defineConstant("WIN_VK_U", WIN_VK_U);
const WIN_VK_V = 0x00000056;
_defineConstant("WIN_VK_V", WIN_VK_V);
const WIN_VK_W = 0x00000057;
_defineConstant("WIN_VK_W", WIN_VK_W);
const WIN_VK_X = 0x00000058;
_defineConstant("WIN_VK_X", WIN_VK_X);
const WIN_VK_Y = 0x00000059;
_defineConstant("WIN_VK_Y", WIN_VK_Y);
const WIN_VK_Z = 0x0000005a;
_defineConstant("WIN_VK_Z", WIN_VK_Z);
const WIN_VK_LWIN = 0xe05b005b;
_defineConstant("WIN_VK_LWIN", WIN_VK_LWIN);
const WIN_VK_RWIN = 0xe05c005c;
_defineConstant("WIN_VK_RWIN", WIN_VK_RWIN);
const WIN_VK_APPS = 0xe05d005d;
_defineConstant("WIN_VK_APPS", WIN_VK_APPS);
const WIN_VK_SLEEP = 0x0000005f;
_defineConstant("WIN_VK_SLEEP", WIN_VK_SLEEP);
const WIN_VK_NUMPAD0 = 0x00520060;
_defineConstant("WIN_VK_NUMPAD0", WIN_VK_NUMPAD0);
const WIN_VK_NUMPAD1 = 0x004f0061;
_defineConstant("WIN_VK_NUMPAD1", WIN_VK_NUMPAD1);
const WIN_VK_NUMPAD2 = 0x00500062;
_defineConstant("WIN_VK_NUMPAD2", WIN_VK_NUMPAD2);
const WIN_VK_NUMPAD3 = 0x00510063;
_defineConstant("WIN_VK_NUMPAD3", WIN_VK_NUMPAD3);
const WIN_VK_NUMPAD4 = 0x004b0064;
_defineConstant("WIN_VK_NUMPAD4", WIN_VK_NUMPAD4);
const WIN_VK_NUMPAD5 = 0x004c0065;
_defineConstant("WIN_VK_NUMPAD5", WIN_VK_NUMPAD5);
const WIN_VK_NUMPAD6 = 0x004d0066;
_defineConstant("WIN_VK_NUMPAD6", WIN_VK_NUMPAD6);
const WIN_VK_NUMPAD7 = 0x00470067;
_defineConstant("WIN_VK_NUMPAD7", WIN_VK_NUMPAD7);
const WIN_VK_NUMPAD8 = 0x00480068;
_defineConstant("WIN_VK_NUMPAD8", WIN_VK_NUMPAD8);
const WIN_VK_NUMPAD9 = 0x00490069;
_defineConstant("WIN_VK_NUMPAD9", WIN_VK_NUMPAD9);
const WIN_VK_MULTIPLY = 0x0037006a;
_defineConstant("WIN_VK_MULTIPLY", WIN_VK_MULTIPLY);
const WIN_VK_ADD = 0x004e006b;
_defineConstant("WIN_VK_ADD", WIN_VK_ADD);
const WIN_VK_SEPARATOR = 0x0000006c;
_defineConstant("WIN_VK_SEPARATOR", WIN_VK_SEPARATOR);
const WIN_VK_OEM_NEC_SEPARATE = 0x0000006c;
_defineConstant("WIN_VK_OEM_NEC_SEPARATE", WIN_VK_OEM_NEC_SEPARATE);
const WIN_VK_SUBTRACT = 0x004a006d;
_defineConstant("WIN_VK_SUBTRACT", WIN_VK_SUBTRACT);
const WIN_VK_DECIMAL = 0x0053006e;
_defineConstant("WIN_VK_DECIMAL", WIN_VK_DECIMAL);
const WIN_VK_DIVIDE = 0xe035006f;
_defineConstant("WIN_VK_DIVIDE", WIN_VK_DIVIDE);
const WIN_VK_F1 = 0x003b0070;
_defineConstant("WIN_VK_F1", WIN_VK_F1);
const WIN_VK_F2 = 0x003c0071;
_defineConstant("WIN_VK_F2", WIN_VK_F2);
const WIN_VK_F3 = 0x003d0072;
_defineConstant("WIN_VK_F3", WIN_VK_F3);
const WIN_VK_F4 = 0x003e0073;
_defineConstant("WIN_VK_F4", WIN_VK_F4);
const WIN_VK_F5 = 0x003f0074;
_defineConstant("WIN_VK_F5", WIN_VK_F5);
const WIN_VK_F6 = 0x00400075;
_defineConstant("WIN_VK_F6", WIN_VK_F6);
const WIN_VK_F7 = 0x00410076;
_defineConstant("WIN_VK_F7", WIN_VK_F7);
const WIN_VK_F8 = 0x00420077;
_defineConstant("WIN_VK_F8", WIN_VK_F8);
const WIN_VK_F9 = 0x00430078;
_defineConstant("WIN_VK_F9", WIN_VK_F9);
const WIN_VK_F10 = 0x00440079;
_defineConstant("WIN_VK_F10", WIN_VK_F10);
const WIN_VK_F11 = 0x0057007a;
_defineConstant("WIN_VK_F11", WIN_VK_F11);
const WIN_VK_F12 = 0x0058007b;
_defineConstant("WIN_VK_F12", WIN_VK_F12);
const WIN_VK_F13 = 0x0064007c;
_defineConstant("WIN_VK_F13", WIN_VK_F13);
const WIN_VK_F14 = 0x0065007d;
_defineConstant("WIN_VK_F14", WIN_VK_F14);
const WIN_VK_F15 = 0x0066007e;
_defineConstant("WIN_VK_F15", WIN_VK_F15);
const WIN_VK_F16 = 0x0067007f;
_defineConstant("WIN_VK_F16", WIN_VK_F16);
const WIN_VK_F17 = 0x00680080;
_defineConstant("WIN_VK_F17", WIN_VK_F17);
const WIN_VK_F18 = 0x00690081;
_defineConstant("WIN_VK_F18", WIN_VK_F18);
const WIN_VK_F19 = 0x006a0082;
_defineConstant("WIN_VK_F19", WIN_VK_F19);
const WIN_VK_F20 = 0x006b0083;
_defineConstant("WIN_VK_F20", WIN_VK_F20);
const WIN_VK_F21 = 0x006c0084;
_defineConstant("WIN_VK_F21", WIN_VK_F21);
const WIN_VK_F22 = 0x006d0085;
_defineConstant("WIN_VK_F22", WIN_VK_F22);
const WIN_VK_F23 = 0x006e0086;
_defineConstant("WIN_VK_F23", WIN_VK_F23);
const WIN_VK_F24 = 0x00760087;
_defineConstant("WIN_VK_F24", WIN_VK_F24);
const WIN_VK_NUMLOCK = 0xe0450090;
_defineConstant("WIN_VK_NUMLOCK", WIN_VK_NUMLOCK);
const WIN_VK_SCROLL = 0x00460091;
_defineConstant("WIN_VK_SCROLL", WIN_VK_SCROLL);
const WIN_VK_OEM_FJ_JISHO = 0x00000092;
_defineConstant("WIN_VK_OEM_FJ_JISHO", WIN_VK_OEM_FJ_JISHO);
const WIN_VK_OEM_NEC_EQUAL = 0x00000092;
_defineConstant("WIN_VK_OEM_NEC_EQUAL", WIN_VK_OEM_NEC_EQUAL);
const WIN_VK_OEM_FJ_MASSHOU = 0x00000093;
_defineConstant("WIN_VK_OEM_FJ_MASSHOU", WIN_VK_OEM_FJ_MASSHOU);
const WIN_VK_OEM_FJ_TOUROKU = 0x00000094;
_defineConstant("WIN_VK_OEM_FJ_TOUROKU", WIN_VK_OEM_FJ_TOUROKU);
const WIN_VK_OEM_FJ_LOYA = 0x00000095;
_defineConstant("WIN_VK_OEM_FJ_LOYA", WIN_VK_OEM_FJ_LOYA);
const WIN_VK_OEM_FJ_ROYA = 0x00000096;
_defineConstant("WIN_VK_OEM_FJ_ROYA", WIN_VK_OEM_FJ_ROYA);
const WIN_VK_LSHIFT = 0x002a00a0;
_defineConstant("WIN_VK_LSHIFT", WIN_VK_LSHIFT);
const WIN_VK_RSHIFT = 0x003600a1;
_defineConstant("WIN_VK_RSHIFT", WIN_VK_RSHIFT);
const WIN_VK_LCONTROL = 0x001d00a2;
_defineConstant("WIN_VK_LCONTROL", WIN_VK_LCONTROL);
const WIN_VK_RCONTROL = 0xe01d00a3;
_defineConstant("WIN_VK_RCONTROL", WIN_VK_RCONTROL);
const WIN_VK_LMENU = 0x003800a4;
_defineConstant("WIN_VK_LMENU", WIN_VK_LMENU);
const WIN_VK_RMENU = 0xe03800a5;
_defineConstant("WIN_VK_RMENU", WIN_VK_RMENU);
const WIN_VK_BROWSER_BACK = 0xe06a00a6;
_defineConstant("WIN_VK_BROWSER_BACK", WIN_VK_BROWSER_BACK);
const WIN_VK_BROWSER_FORWARD = 0xe06900a7;
_defineConstant("WIN_VK_BROWSER_FORWARD", WIN_VK_BROWSER_FORWARD);
const WIN_VK_BROWSER_REFRESH = 0xe06700a8;
_defineConstant("WIN_VK_BROWSER_REFRESH", WIN_VK_BROWSER_REFRESH);
const WIN_VK_BROWSER_STOP = 0xe06800a9;
_defineConstant("WIN_VK_BROWSER_STOP", WIN_VK_BROWSER_STOP);
const WIN_VK_BROWSER_SEARCH = 0x000000aa;
_defineConstant("WIN_VK_BROWSER_SEARCH", WIN_VK_BROWSER_SEARCH);
const WIN_VK_BROWSER_FAVORITES = 0xe06600ab;
_defineConstant("WIN_VK_BROWSER_FAVORITES", WIN_VK_BROWSER_FAVORITES);
const WIN_VK_BROWSER_HOME = 0xe03200ac;
_defineConstant("WIN_VK_BROWSER_HOME", WIN_VK_BROWSER_HOME);
const WIN_VK_VOLUME_MUTE = 0xe02000ad;
_defineConstant("WIN_VK_VOLUME_MUTE", WIN_VK_VOLUME_MUTE);
const WIN_VK_VOLUME_DOWN = 0xe02e00ae;
_defineConstant("WIN_VK_VOLUME_DOWN", WIN_VK_VOLUME_DOWN);
const WIN_VK_VOLUME_UP = 0xe03000af;
_defineConstant("WIN_VK_VOLUME_UP", WIN_VK_VOLUME_UP);
const WIN_VK_MEDIA_NEXT_TRACK = 0xe01900b0;
_defineConstant("WIN_VK_MEDIA_NEXT_TRACK", WIN_VK_MEDIA_NEXT_TRACK);
const WIN_VK_OEM_FJ_000 = 0x000000b0;
_defineConstant("WIN_VK_OEM_FJ_000", WIN_VK_OEM_FJ_000);
const WIN_VK_MEDIA_PREV_TRACK = 0xe01000b1;
_defineConstant("WIN_VK_MEDIA_PREV_TRACK", WIN_VK_MEDIA_PREV_TRACK);
const WIN_VK_OEM_FJ_EUQAL = 0x000000b1;
_defineConstant("WIN_VK_OEM_FJ_EUQAL", WIN_VK_OEM_FJ_EUQAL);
const WIN_VK_MEDIA_STOP = 0xe02400b2;
_defineConstant("WIN_VK_MEDIA_STOP", WIN_VK_MEDIA_STOP);
const WIN_VK_MEDIA_PLAY_PAUSE = 0xe02200b3;
_defineConstant("WIN_VK_MEDIA_PLAY_PAUSE", WIN_VK_MEDIA_PLAY_PAUSE);
const WIN_VK_OEM_FJ_00 = 0x000000b3;
_defineConstant("WIN_VK_OEM_FJ_00", WIN_VK_OEM_FJ_00);
const WIN_VK_LAUNCH_MAIL = 0xe06c00b4;
_defineConstant("WIN_VK_LAUNCH_MAIL", WIN_VK_LAUNCH_MAIL);
const WIN_VK_LAUNCH_MEDIA_SELECT = 0xe06d00b5;
_defineConstant("WIN_VK_LAUNCH_MEDIA_SELECT", WIN_VK_LAUNCH_MEDIA_SELECT);
const WIN_VK_LAUNCH_APP1 = 0xe06b00b6;
_defineConstant("WIN_VK_LAUNCH_APP1", WIN_VK_LAUNCH_APP1);
const WIN_VK_LAUNCH_APP2 = 0xe02100b7;
_defineConstant("WIN_VK_LAUNCH_APP2", WIN_VK_LAUNCH_APP2);
const WIN_VK_OEM_1 = 0x000000ba;
_defineConstant("WIN_VK_OEM_1", WIN_VK_OEM_1);
const WIN_VK_OEM_PLUS = 0x000000bb;
_defineConstant("WIN_VK_OEM_PLUS", WIN_VK_OEM_PLUS);
const WIN_VK_OEM_COMMA = 0x000000bc;
_defineConstant("WIN_VK_OEM_COMMA", WIN_VK_OEM_COMMA);
const WIN_VK_OEM_MINUS = 0x000000bd;
_defineConstant("WIN_VK_OEM_MINUS", WIN_VK_OEM_MINUS);
const WIN_VK_OEM_PERIOD = 0x000000be;
_defineConstant("WIN_VK_OEM_PERIOD", WIN_VK_OEM_PERIOD);
const WIN_VK_OEM_2 = 0x000000bf;
_defineConstant("WIN_VK_OEM_2", WIN_VK_OEM_2);
const WIN_VK_OEM_3 = 0x000000c0;
_defineConstant("WIN_VK_OEM_3", WIN_VK_OEM_3);
const WIN_VK_ABNT_C1 = 0x005600c1;
_defineConstant("WIN_VK_ABNT_C1", WIN_VK_ABNT_C1);
const WIN_VK_ABNT_C2 = 0x000000c2;
_defineConstant("WIN_VK_ABNT_C2", WIN_VK_ABNT_C2);
const WIN_VK_OEM_4 = 0x000000db;
_defineConstant("WIN_VK_OEM_4", WIN_VK_OEM_4);
const WIN_VK_OEM_5 = 0x000000dc;
_defineConstant("WIN_VK_OEM_5", WIN_VK_OEM_5);
const WIN_VK_OEM_6 = 0x000000dd;
_defineConstant("WIN_VK_OEM_6", WIN_VK_OEM_6);
const WIN_VK_OEM_7 = 0x000000de;
_defineConstant("WIN_VK_OEM_7", WIN_VK_OEM_7);
const WIN_VK_OEM_8 = 0x000000df;
_defineConstant("WIN_VK_OEM_8", WIN_VK_OEM_8);
const WIN_VK_OEM_NEC_DP1 = 0x000000e0;
_defineConstant("WIN_VK_OEM_NEC_DP1", WIN_VK_OEM_NEC_DP1);
const WIN_VK_OEM_AX = 0x000000e1;
_defineConstant("WIN_VK_OEM_AX", WIN_VK_OEM_AX);
const WIN_VK_OEM_NEC_DP2 = 0x000000e1;
_defineConstant("WIN_VK_OEM_NEC_DP2", WIN_VK_OEM_NEC_DP2);
const WIN_VK_OEM_102 = 0x000000e2;
_defineConstant("WIN_VK_OEM_102", WIN_VK_OEM_102);
const WIN_VK_OEM_NEC_DP3 = 0x000000e2;
_defineConstant("WIN_VK_OEM_NEC_DP3", WIN_VK_OEM_NEC_DP3);
const WIN_VK_ICO_HELP = 0x000000e3;
_defineConstant("WIN_VK_ICO_HELP", WIN_VK_ICO_HELP);
const WIN_VK_OEM_NEC_DP4 = 0x000000e3;
_defineConstant("WIN_VK_OEM_NEC_DP4", WIN_VK_OEM_NEC_DP4);
const WIN_VK_ICO_00 = 0x000000e4;
_defineConstant("WIN_VK_ICO_00", WIN_VK_ICO_00);
const WIN_VK_PROCESSKEY = 0x000000e5;
_defineConstant("WIN_VK_PROCESSKEY", WIN_VK_PROCESSKEY);
const WIN_VK_ICO_CLEAR = 0x000000e6;
_defineConstant("WIN_VK_ICO_CLEAR", WIN_VK_ICO_CLEAR);
const WIN_VK_PACKET = 0x000000e7;
_defineConstant("WIN_VK_PACKET", WIN_VK_PACKET);
const WIN_VK_ERICSSON_BASE = 0x000000e8;
_defineConstant("WIN_VK_ERICSSON_BASE", WIN_VK_ERICSSON_BASE);
const WIN_VK_OEM_RESET = 0x000000e9;
_defineConstant("WIN_VK_OEM_RESET", WIN_VK_OEM_RESET);
const WIN_VK_OEM_JUMP = 0x000000ea;
_defineConstant("WIN_VK_OEM_JUMP", WIN_VK_OEM_JUMP);
const WIN_VK_OEM_PA1 = 0x000000eb;
_defineConstant("WIN_VK_OEM_PA1", WIN_VK_OEM_PA1);
const WIN_VK_OEM_PA2 = 0x000000ec;
_defineConstant("WIN_VK_OEM_PA2", WIN_VK_OEM_PA2);
const WIN_VK_OEM_PA3 = 0x000000ed;
_defineConstant("WIN_VK_OEM_PA3", WIN_VK_OEM_PA3);
const WIN_VK_OEM_WSCTRL = 0x000000ee;
_defineConstant("WIN_VK_OEM_WSCTRL", WIN_VK_OEM_WSCTRL);
const WIN_VK_OEM_CUSEL = 0x000000ef;
_defineConstant("WIN_VK_OEM_CUSEL", WIN_VK_OEM_CUSEL);
const WIN_VK_OEM_ATTN = 0x000000f0;
_defineConstant("WIN_VK_OEM_ATTN", WIN_VK_OEM_ATTN);
const WIN_VK_OEM_FINISH = 0x000000f1;
_defineConstant("WIN_VK_OEM_FINISH", WIN_VK_OEM_FINISH);
const WIN_VK_OEM_COPY = 0x000000f2;
_defineConstant("WIN_VK_OEM_COPY", WIN_VK_OEM_COPY);
const WIN_VK_OEM_AUTO = 0x000000f3;
_defineConstant("WIN_VK_OEM_AUTO", WIN_VK_OEM_AUTO);
const WIN_VK_OEM_ENLW = 0x000000f4;
_defineConstant("WIN_VK_OEM_ENLW", WIN_VK_OEM_ENLW);
const WIN_VK_OEM_BACKTAB = 0x000000f5;
_defineConstant("WIN_VK_OEM_BACKTAB", WIN_VK_OEM_BACKTAB);
const WIN_VK_ATTN = 0x000000f6;
_defineConstant("WIN_VK_ATTN", WIN_VK_ATTN);
const WIN_VK_CRSEL = 0x000000f7;
_defineConstant("WIN_VK_CRSEL", WIN_VK_CRSEL);
const WIN_VK_EXSEL = 0x000000f8;
_defineConstant("WIN_VK_EXSEL", WIN_VK_EXSEL);
const WIN_VK_EREOF = 0x000000f9;
_defineConstant("WIN_VK_EREOF", WIN_VK_EREOF);
const WIN_VK_PLAY = 0x000000fa;
_defineConstant("WIN_VK_PLAY", WIN_VK_PLAY);
const WIN_VK_ZOOM = 0x000000fb;
_defineConstant("WIN_VK_ZOOM", WIN_VK_ZOOM);
const WIN_VK_NONAME = 0x000000fc;
_defineConstant("WIN_VK_NONAME", WIN_VK_NONAME);
const WIN_VK_PA1 = 0x000000fd;
_defineConstant("WIN_VK_PA1", WIN_VK_PA1);
const WIN_VK_OEM_CLEAR = 0x000000fe;
_defineConstant("WIN_VK_OEM_CLEAR", WIN_VK_OEM_CLEAR);
const WIN_VK_NUMPAD_RETURN = 0xe01c000d;
_defineConstant("WIN_VK_NUMPAD_RETURN", WIN_VK_NUMPAD_RETURN);
const WIN_VK_NUMPAD_PRIOR = 0x00490021;
_defineConstant("WIN_VK_NUMPAD_PRIOR", WIN_VK_NUMPAD_PRIOR);
const WIN_VK_NUMPAD_NEXT = 0x00510022;
_defineConstant("WIN_VK_NUMPAD_NEXT", WIN_VK_NUMPAD_NEXT);
const WIN_VK_NUMPAD_END = 0x004f0023;
_defineConstant("WIN_VK_NUMPAD_END", WIN_VK_NUMPAD_END);
const WIN_VK_NUMPAD_HOME = 0x00470024;
_defineConstant("WIN_VK_NUMPAD_HOME", WIN_VK_NUMPAD_HOME);
const WIN_VK_NUMPAD_LEFT = 0x004b0025;
_defineConstant("WIN_VK_NUMPAD_LEFT", WIN_VK_NUMPAD_LEFT);
const WIN_VK_NUMPAD_UP = 0x00480026;
_defineConstant("WIN_VK_NUMPAD_UP", WIN_VK_NUMPAD_UP);
const WIN_VK_NUMPAD_RIGHT = 0x004d0027;
_defineConstant("WIN_VK_NUMPAD_RIGHT", WIN_VK_NUMPAD_RIGHT);
const WIN_VK_NUMPAD_DOWN = 0x00500028;
_defineConstant("WIN_VK_NUMPAD_DOWN", WIN_VK_NUMPAD_DOWN);
const WIN_VK_NUMPAD_INSERT = 0x0052002d;
_defineConstant("WIN_VK_NUMPAD_INSERT", WIN_VK_NUMPAD_INSERT);
const WIN_VK_NUMPAD_DELETE = 0x0053002e;
_defineConstant("WIN_VK_NUMPAD_DELETE", WIN_VK_NUMPAD_DELETE);
// Mac
const MAC_VK_ANSI_A = 0x00;
_defineConstant("MAC_VK_ANSI_A", MAC_VK_ANSI_A);
const MAC_VK_ANSI_S = 0x01;
_defineConstant("MAC_VK_ANSI_S", MAC_VK_ANSI_S);
const MAC_VK_ANSI_D = 0x02;
_defineConstant("MAC_VK_ANSI_D", MAC_VK_ANSI_D);
const MAC_VK_ANSI_F = 0x03;
_defineConstant("MAC_VK_ANSI_F", MAC_VK_ANSI_F);
const MAC_VK_ANSI_H = 0x04;
_defineConstant("MAC_VK_ANSI_H", MAC_VK_ANSI_H);
const MAC_VK_ANSI_G = 0x05;
_defineConstant("MAC_VK_ANSI_G", MAC_VK_ANSI_G);
const MAC_VK_ANSI_Z = 0x06;
_defineConstant("MAC_VK_ANSI_Z", MAC_VK_ANSI_Z);
const MAC_VK_ANSI_X = 0x07;
_defineConstant("MAC_VK_ANSI_X", MAC_VK_ANSI_X);
const MAC_VK_ANSI_C = 0x08;
_defineConstant("MAC_VK_ANSI_C", MAC_VK_ANSI_C);
const MAC_VK_ANSI_V = 0x09;
_defineConstant("MAC_VK_ANSI_V", MAC_VK_ANSI_V);
const MAC_VK_ISO_Section = 0x0a;
_defineConstant("MAC_VK_ISO_Section", MAC_VK_ISO_Section);
const MAC_VK_ANSI_B = 0x0b;
_defineConstant("MAC_VK_ANSI_B", MAC_VK_ANSI_B);
const MAC_VK_ANSI_Q = 0x0c;
_defineConstant("MAC_VK_ANSI_Q", MAC_VK_ANSI_Q);
const MAC_VK_ANSI_W = 0x0d;
_defineConstant("MAC_VK_ANSI_W", MAC_VK_ANSI_W);
const MAC_VK_ANSI_E = 0x0e;
_defineConstant("MAC_VK_ANSI_E", MAC_VK_ANSI_E);
const MAC_VK_ANSI_R = 0x0f;
_defineConstant("MAC_VK_ANSI_R", MAC_VK_ANSI_R);
const MAC_VK_ANSI_Y = 0x10;
_defineConstant("MAC_VK_ANSI_Y", MAC_VK_ANSI_Y);
const MAC_VK_ANSI_T = 0x11;
_defineConstant("MAC_VK_ANSI_T", MAC_VK_ANSI_T);
const MAC_VK_ANSI_1 = 0x12;
_defineConstant("MAC_VK_ANSI_1", MAC_VK_ANSI_1);
const MAC_VK_ANSI_2 = 0x13;
_defineConstant("MAC_VK_ANSI_2", MAC_VK_ANSI_2);
const MAC_VK_ANSI_3 = 0x14;
_defineConstant("MAC_VK_ANSI_3", MAC_VK_ANSI_3);
const MAC_VK_ANSI_4 = 0x15;
_defineConstant("MAC_VK_ANSI_4", MAC_VK_ANSI_4);
const MAC_VK_ANSI_6 = 0x16;
_defineConstant("MAC_VK_ANSI_6", MAC_VK_ANSI_6);
const MAC_VK_ANSI_5 = 0x17;
_defineConstant("MAC_VK_ANSI_5", MAC_VK_ANSI_5);
const MAC_VK_ANSI_Equal = 0x18;
_defineConstant("MAC_VK_ANSI_Equal", MAC_VK_ANSI_Equal);
const MAC_VK_ANSI_9 = 0x19;
_defineConstant("MAC_VK_ANSI_9", MAC_VK_ANSI_9);
const MAC_VK_ANSI_7 = 0x1a;
_defineConstant("MAC_VK_ANSI_7", MAC_VK_ANSI_7);
const MAC_VK_ANSI_Minus = 0x1b;
_defineConstant("MAC_VK_ANSI_Minus", MAC_VK_ANSI_Minus);
const MAC_VK_ANSI_8 = 0x1c;
_defineConstant("MAC_VK_ANSI_8", MAC_VK_ANSI_8);
const MAC_VK_ANSI_0 = 0x1d;
_defineConstant("MAC_VK_ANSI_0", MAC_VK_ANSI_0);
const MAC_VK_ANSI_RightBracket = 0x1e;
_defineConstant("MAC_VK_ANSI_RightBracket", MAC_VK_ANSI_RightBracket);
const MAC_VK_ANSI_O = 0x1f;
_defineConstant("MAC_VK_ANSI_O", MAC_VK_ANSI_O);
const MAC_VK_ANSI_U = 0x20;
_defineConstant("MAC_VK_ANSI_U", MAC_VK_ANSI_U);
const MAC_VK_ANSI_LeftBracket = 0x21;
_defineConstant("MAC_VK_ANSI_LeftBracket", MAC_VK_ANSI_LeftBracket);
const MAC_VK_ANSI_I = 0x22;
_defineConstant("MAC_VK_ANSI_I", MAC_VK_ANSI_I);
const MAC_VK_ANSI_P = 0x23;
_defineConstant("MAC_VK_ANSI_P", MAC_VK_ANSI_P);
const MAC_VK_Return = 0x24;
_defineConstant("MAC_VK_Return", MAC_VK_Return);
const MAC_VK_ANSI_L = 0x25;
_defineConstant("MAC_VK_ANSI_L", MAC_VK_ANSI_L);
const MAC_VK_ANSI_J = 0x26;
_defineConstant("MAC_VK_ANSI_J", MAC_VK_ANSI_J);
const MAC_VK_ANSI_Quote = 0x27;
_defineConstant("MAC_VK_ANSI_Quote", MAC_VK_ANSI_Quote);
const MAC_VK_ANSI_K = 0x28;
_defineConstant("MAC_VK_ANSI_K", MAC_VK_ANSI_K);
const MAC_VK_ANSI_Semicolon = 0x29;
_defineConstant("MAC_VK_ANSI_Semicolon", MAC_VK_ANSI_Semicolon);
const MAC_VK_ANSI_Backslash = 0x2a;
_defineConstant("MAC_VK_ANSI_Backslash", MAC_VK_ANSI_Backslash);
const MAC_VK_ANSI_Comma = 0x2b;
_defineConstant("MAC_VK_ANSI_Comma", MAC_VK_ANSI_Comma);
const MAC_VK_ANSI_Slash = 0x2c;
_defineConstant("MAC_VK_ANSI_Slash", MAC_VK_ANSI_Slash);
const MAC_VK_ANSI_N = 0x2d;
_defineConstant("MAC_VK_ANSI_N", MAC_VK_ANSI_N);
const MAC_VK_ANSI_M = 0x2e;
_defineConstant("MAC_VK_ANSI_M", MAC_VK_ANSI_M);
const MAC_VK_ANSI_Period = 0x2f;
_defineConstant("MAC_VK_ANSI_Period", MAC_VK_ANSI_Period);
const MAC_VK_Tab = 0x30;
_defineConstant("MAC_VK_Tab", MAC_VK_Tab);
const MAC_VK_Space = 0x31;
_defineConstant("MAC_VK_Space", MAC_VK_Space);
const MAC_VK_ANSI_Grave = 0x32;
_defineConstant("MAC_VK_ANSI_Grave", MAC_VK_ANSI_Grave);
const MAC_VK_Delete = 0x33;
_defineConstant("MAC_VK_Delete", MAC_VK_Delete);
const MAC_VK_PC_Backspace = 0x33;
_defineConstant("MAC_VK_PC_Backspace", MAC_VK_PC_Backspace);
const MAC_VK_Powerbook_KeypadEnter = 0x34;
_defineConstant("MAC_VK_Powerbook_KeypadEnter", MAC_VK_Powerbook_KeypadEnter);
const MAC_VK_Escape = 0x35;
_defineConstant("MAC_VK_Escape", MAC_VK_Escape);
const MAC_VK_RightCommand = 0x36;
_defineConstant("MAC_VK_RightCommand", MAC_VK_RightCommand);
const MAC_VK_Command = 0x37;
_defineConstant("MAC_VK_Command", MAC_VK_Command);
const MAC_VK_Shift = 0x38;
_defineConstant("MAC_VK_Shift", MAC_VK_Shift);
const MAC_VK_CapsLock = 0x39;
_defineConstant("MAC_VK_CapsLock", MAC_VK_CapsLock);
const MAC_VK_Option = 0x3a;
_defineConstant("MAC_VK_Option", MAC_VK_Option);
const MAC_VK_Control = 0x3b;
_defineConstant("MAC_VK_Control", MAC_VK_Control);
const MAC_VK_RightShift = 0x3c;
_defineConstant("MAC_VK_RightShift", MAC_VK_RightShift);
const MAC_VK_RightOption = 0x3d;
_defineConstant("MAC_VK_RightOption", MAC_VK_RightOption);
const MAC_VK_RightControl = 0x3e;
_defineConstant("MAC_VK_RightControl", MAC_VK_RightControl);
const MAC_VK_Function = 0x3f;
_defineConstant("MAC_VK_Function", MAC_VK_Function);
const MAC_VK_F17 = 0x40;
_defineConstant("MAC_VK_F17", MAC_VK_F17);
const MAC_VK_ANSI_KeypadDecimal = 0x41;
_defineConstant("MAC_VK_ANSI_KeypadDecimal", MAC_VK_ANSI_KeypadDecimal);
const MAC_VK_ANSI_KeypadMultiply = 0x43;
_defineConstant("MAC_VK_ANSI_KeypadMultiply", MAC_VK_ANSI_KeypadMultiply);
const MAC_VK_ANSI_KeypadPlus = 0x45;
_defineConstant("MAC_VK_ANSI_KeypadPlus", MAC_VK_ANSI_KeypadPlus);
const MAC_VK_ANSI_KeypadClear = 0x47;
_defineConstant("MAC_VK_ANSI_KeypadClear", MAC_VK_ANSI_KeypadClear);
const MAC_VK_VolumeUp = 0x48;
_defineConstant("MAC_VK_VolumeUp", MAC_VK_VolumeUp);
const MAC_VK_VolumeDown = 0x49;
_defineConstant("MAC_VK_VolumeDown", MAC_VK_VolumeDown);
const MAC_VK_Mute = 0x4a;
_defineConstant("MAC_VK_Mute", MAC_VK_Mute);
const MAC_VK_ANSI_KeypadDivide = 0x4b;
_defineConstant("MAC_VK_ANSI_KeypadDivide", MAC_VK_ANSI_KeypadDivide);
const MAC_VK_ANSI_KeypadEnter = 0x4c;
_defineConstant("MAC_VK_ANSI_KeypadEnter", MAC_VK_ANSI_KeypadEnter);
const MAC_VK_ANSI_KeypadMinus = 0x4e;
_defineConstant("MAC_VK_ANSI_KeypadMinus", MAC_VK_ANSI_KeypadMinus);
const MAC_VK_F18 = 0x4f;
_defineConstant("MAC_VK_F18", MAC_VK_F18);
const MAC_VK_F19 = 0x50;
_defineConstant("MAC_VK_F19", MAC_VK_F19);
const MAC_VK_ANSI_KeypadEquals = 0x51;
_defineConstant("MAC_VK_ANSI_KeypadEquals", MAC_VK_ANSI_KeypadEquals);
const MAC_VK_ANSI_Keypad0 = 0x52;
_defineConstant("MAC_VK_ANSI_Keypad0", MAC_VK_ANSI_Keypad0);
const MAC_VK_ANSI_Keypad1 = 0x53;
_defineConstant("MAC_VK_ANSI_Keypad1", MAC_VK_ANSI_Keypad1);
const MAC_VK_ANSI_Keypad2 = 0x54;
_defineConstant("MAC_VK_ANSI_Keypad2", MAC_VK_ANSI_Keypad2);
const MAC_VK_ANSI_Keypad3 = 0x55;
_defineConstant("MAC_VK_ANSI_Keypad3", MAC_VK_ANSI_Keypad3);
const MAC_VK_ANSI_Keypad4 = 0x56;
_defineConstant("MAC_VK_ANSI_Keypad4", MAC_VK_ANSI_Keypad4);
const MAC_VK_ANSI_Keypad5 = 0x57;
_defineConstant("MAC_VK_ANSI_Keypad5", MAC_VK_ANSI_Keypad5);
const MAC_VK_ANSI_Keypad6 = 0x58;
_defineConstant("MAC_VK_ANSI_Keypad6", MAC_VK_ANSI_Keypad6);
const MAC_VK_ANSI_Keypad7 = 0x59;
_defineConstant("MAC_VK_ANSI_Keypad7", MAC_VK_ANSI_Keypad7);
const MAC_VK_F20 = 0x5a;
_defineConstant("MAC_VK_F20", MAC_VK_F20);
const MAC_VK_ANSI_Keypad8 = 0x5b;
_defineConstant("MAC_VK_ANSI_Keypad8", MAC_VK_ANSI_Keypad8);
const MAC_VK_ANSI_Keypad9 = 0x5c;
_defineConstant("MAC_VK_ANSI_Keypad9", MAC_VK_ANSI_Keypad9);
const MAC_VK_JIS_Yen = 0x5d;
_defineConstant("MAC_VK_JIS_Yen", MAC_VK_JIS_Yen);
const MAC_VK_JIS_Underscore = 0x5e;
_defineConstant("MAC_VK_JIS_Underscore", MAC_VK_JIS_Underscore);
const MAC_VK_JIS_KeypadComma = 0x5f;
_defineConstant("MAC_VK_JIS_KeypadComma", MAC_VK_JIS_KeypadComma);
const MAC_VK_F5 = 0x60;
_defineConstant("MAC_VK_F5", MAC_VK_F5);
const MAC_VK_F6 = 0x61;
_defineConstant("MAC_VK_F6", MAC_VK_F6);
const MAC_VK_F7 = 0x62;
_defineConstant("MAC_VK_F7", MAC_VK_F7);
const MAC_VK_F3 = 0x63;
_defineConstant("MAC_VK_F3", MAC_VK_F3);
const MAC_VK_F8 = 0x64;
_defineConstant("MAC_VK_F8", MAC_VK_F8);
const MAC_VK_F9 = 0x65;
_defineConstant("MAC_VK_F9", MAC_VK_F9);
const MAC_VK_JIS_Eisu = 0x66;
_defineConstant("MAC_VK_JIS_Eisu", MAC_VK_JIS_Eisu);
const MAC_VK_F11 = 0x67;
_defineConstant("MAC_VK_F11", MAC_VK_F11);
const MAC_VK_JIS_Kana = 0x68;
_defineConstant("MAC_VK_JIS_Kana", MAC_VK_JIS_Kana);
const MAC_VK_F13 = 0x69;
_defineConstant("MAC_VK_F13", MAC_VK_F13);
const MAC_VK_PC_PrintScreen = 0x69;
_defineConstant("MAC_VK_PC_PrintScreen", MAC_VK_PC_PrintScreen);
const MAC_VK_F16 = 0x6a;
_defineConstant("MAC_VK_F16", MAC_VK_F16);
const MAC_VK_F14 = 0x6b;
_defineConstant("MAC_VK_F14", MAC_VK_F14);
const MAC_VK_PC_ScrollLock = 0x6b;
_defineConstant("MAC_VK_PC_ScrollLock", MAC_VK_PC_ScrollLock);
const MAC_VK_F10 = 0x6d;
_defineConstant("MAC_VK_F10", MAC_VK_F10);
const MAC_VK_PC_ContextMenu = 0x6e;
_defineConstant("MAC_VK_PC_ContextMenu", MAC_VK_PC_ContextMenu);
const MAC_VK_F12 = 0x6f;
_defineConstant("MAC_VK_F12", MAC_VK_F12);
const MAC_VK_F15 = 0x71;
_defineConstant("MAC_VK_F15", MAC_VK_F15);
const MAC_VK_PC_Pause = 0x71;
_defineConstant("MAC_VK_PC_Pause", MAC_VK_PC_Pause);
const MAC_VK_Help = 0x72;
_defineConstant("MAC_VK_Help", MAC_VK_Help);
const MAC_VK_PC_Insert = 0x72;
_defineConstant("MAC_VK_PC_Insert", MAC_VK_PC_Insert);
const MAC_VK_Home = 0x73;
_defineConstant("MAC_VK_Home", MAC_VK_Home);
const MAC_VK_PageUp = 0x74;
_defineConstant("MAC_VK_PageUp", MAC_VK_PageUp);
const MAC_VK_ForwardDelete = 0x75;
_defineConstant("MAC_VK_ForwardDelete", MAC_VK_ForwardDelete);
const MAC_VK_PC_Delete = 0x75;
_defineConstant("MAC_VK_PC_Delete", MAC_VK_PC_Delete);
const MAC_VK_F4 = 0x76;
_defineConstant("MAC_VK_F4", MAC_VK_F4);
const MAC_VK_End = 0x77;
_defineConstant("MAC_VK_End", MAC_VK_End);
const MAC_VK_F2 = 0x78;
_defineConstant("MAC_VK_F2", MAC_VK_F2);
const MAC_VK_PageDown = 0x79;
_defineConstant("MAC_VK_PageDown", MAC_VK_PageDown);
const MAC_VK_F1 = 0x7a;
_defineConstant("MAC_VK_F1", MAC_VK_F1);
const MAC_VK_LeftArrow = 0x7b;
_defineConstant("MAC_VK_LeftArrow", MAC_VK_LeftArrow);
const MAC_VK_RightArrow = 0x7c;
_defineConstant("MAC_VK_RightArrow", MAC_VK_RightArrow);
const MAC_VK_DownArrow = 0x7d;
_defineConstant("MAC_VK_DownArrow", MAC_VK_DownArrow);
const MAC_VK_UpArrow = 0x7e;
_defineConstant("MAC_VK_UpArrow", MAC_VK_UpArrow);

View file

@ -104,14 +104,43 @@ struct AlternativeCharCode {
******************************************************************************/
struct ShortcutKeyCandidate {
ShortcutKeyCandidate() : mCharCode(0), mIgnoreShift(0) {}
ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
: mCharCode(aCharCode), mIgnoreShift(aIgnoreShift) {}
enum class ShiftState : bool {
// Can ignore `Shift` modifier state when comparing the key combination.
// E.g., Ctrl + Shift + `:` in the US keyboard layout may match with
// Ctrl + `:` shortcut.
Ignorable,
// `Shift` modifier state should be respected. I.e., Ctrl + `;` in the US
// keyboard layout never matches with Ctrl + Shift + `;` shortcut.
MatchExactly,
};
enum class SkipIfEarlierHandlerDisabled : bool {
// Even if an earlier handler is disabled, this may match with another
// handler for avoiding inaccessible shortcut with the active keyboard
// layout.
No,
// If an earlier handler (i.e., preferred handler) is disabled, this should
// not try to match. E.g., Ctrl + `-` in the French keyboard layout when
// the zoom level is the minimum value, it should not match with Ctrl + `6`
// shortcut (French keyboard layout introduces `-` when pressing Digit6 key
// without Shift, and Shift + Digit6 introduces `6`).
Yes,
};
ShortcutKeyCandidate() = default;
ShortcutKeyCandidate(
uint32_t aCharCode, ShiftState aShiftState,
SkipIfEarlierHandlerDisabled aSkipIfEarlierHandlerDisabled)
: mCharCode(aCharCode),
mShiftState(aShiftState),
mSkipIfEarlierHandlerDisabled(aSkipIfEarlierHandlerDisabled) {}
// The mCharCode value which must match keyboard shortcut definition.
uint32_t mCharCode;
// true if Shift state can be ignored. Otherwise, Shift key state must
// match keyboard shortcut definition.
bool mIgnoreShift;
uint32_t mCharCode = 0;
ShiftState mShiftState = ShiftState::MatchExactly;
SkipIfEarlierHandlerDisabled mSkipIfEarlierHandlerDisabled =
SkipIfEarlierHandlerDisabled::No;
};
/******************************************************************************

View file

@ -952,20 +952,28 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
ShortcutKeyCandidateArray& aCandidates) const {
MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
using ShiftState = ShortcutKeyCandidate::ShiftState;
using SkipIfEarlierHandlerDisabled =
ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled;
// ShortcutKeyCandidate::mCharCode is a candidate charCode.
// ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
// execute a command with/without shift key state. If this is TRUE, the
// shifted key state should be ignored. Otherwise, don't ignore the state.
// ShortcutKeyCandidate::mShiftState means the mCharCode should be tried to
// execute a command with/without shift key state. If this is Ignorable,
// the shifted key state should be ignored. Otherwise, don't ignore the state.
// the priority of the charCodes are (shift key is not pressed):
// 0: PseudoCharCode()/false,
// 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
// 0: PseudoCharCode()/ShiftState::MatchExactly,
// 1: unshiftedCharCodes[0]/ShiftState::MatchExactly,
// 2: unshiftedCharCodes[1]/ShiftState::MatchExactly...
// the priority of the charCodes are (shift key is pressed):
// 0: PseudoCharCode()/false,
// 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
// 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
// 0: PseudoCharCode()/ShiftState::MatchExactly,
// 1: shiftedCharCodes[0]/ShiftState::MatchExactly,
// 2: shiftedCharCodes[0]/ShiftState::Ignorable,
// 3: shiftedCharCodes[1]/ShiftState::MatchExactly,
// 4: shiftedCharCodes[1]/ShiftState::Ignorable...
uint32_t pseudoCharCode = PseudoCharCode();
if (pseudoCharCode) {
ShortcutKeyCandidate key(pseudoCharCode, false);
ShortcutKeyCandidate key(pseudoCharCode, ShiftState::MatchExactly,
SkipIfEarlierHandlerDisabled::No);
aCandidates.AppendElement(key);
}
@ -976,7 +984,8 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
if (!ch || ch == pseudoCharCode) {
continue;
}
ShortcutKeyCandidate key(ch, false);
ShortcutKeyCandidate key(ch, ShiftState::MatchExactly,
SkipIfEarlierHandlerDisabled::No);
aCandidates.AppendElement(key);
}
// If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
@ -987,7 +996,11 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
for (uint32_t i = 0; i < len; ++i) {
uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
if (ch >= '0' && ch <= '9') {
ShortcutKeyCandidate key(ch, false);
ShortcutKeyCandidate key(
ch, ShiftState::MatchExactly,
// Ctrl + `-` in the French keyboard layout should not match with
// Ctrl + `6` shortcut when it's already fully zoomed out.
SkipIfEarlierHandlerDisabled::Yes);
aCandidates.AppendElement(key);
break;
}
@ -1001,7 +1014,8 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
}
if (ch != pseudoCharCode) {
ShortcutKeyCandidate key(ch, false);
ShortcutKeyCandidate key(ch, ShiftState::MatchExactly,
SkipIfEarlierHandlerDisabled::No);
aCandidates.AppendElement(key);
}
@ -1024,7 +1038,8 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
// Setting the alternative charCode candidates for retry without shift
// key state only when the shift key is pressed.
ShortcutKeyCandidate key(ch, true);
ShortcutKeyCandidate key(ch, ShiftState::Ignorable,
SkipIfEarlierHandlerDisabled::No);
aCandidates.AppendElement(key);
}
}
@ -1036,7 +1051,8 @@ void WidgetKeyboardEvent::GetShortcutKeyCandidates(
// shouldn't work as a space key.
if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
ShortcutKeyCandidate spaceKey(' ', false);
ShortcutKeyCandidate spaceKey(' ', ShiftState::MatchExactly,
SkipIfEarlierHandlerDisabled::No);
aCandidates.AppendElement(spaceKey);
}
}

View file

@ -705,6 +705,9 @@ void TISInputSourceWrapper::InitByLayoutID(SInt32 aLayoutID, bool aOverrideKeybo
case 12:
InitByInputSourceID("com.apple.keylayout.Spanish");
break;
case 13:
InitByInputSourceID("com.apple.keylayout.French-PC");
break;
default:
Clear();
break;

View file

@ -378,18 +378,34 @@ struct ParamTraits<mozilla::AlternativeCharCode> {
}
};
template <>
struct ParamTraits<mozilla::ShortcutKeyCandidate::ShiftState>
: public ContiguousEnumSerializerInclusive<
mozilla::ShortcutKeyCandidate::ShiftState,
mozilla::ShortcutKeyCandidate::ShiftState::Ignorable,
mozilla::ShortcutKeyCandidate::ShiftState::MatchExactly> {};
template <>
struct ParamTraits<mozilla::ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled>
: public ContiguousEnumSerializerInclusive<
mozilla::ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled,
mozilla::ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled::No,
mozilla::ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled::Yes> {};
template <>
struct ParamTraits<mozilla::ShortcutKeyCandidate> {
using paramType = mozilla::ShortcutKeyCandidate;
static void Write(MessageWriter* aWriter, const paramType& aParam) {
WriteParam(aWriter, aParam.mCharCode);
WriteParam(aWriter, aParam.mIgnoreShift);
WriteParam(aWriter, aParam.mShiftState);
WriteParam(aWriter, aParam.mSkipIfEarlierHandlerDisabled);
}
static bool Read(MessageReader* aReader, paramType* aResult) {
return ReadParam(aReader, &aResult->mCharCode) &&
ReadParam(aReader, &aResult->mIgnoreShift);
ReadParam(aReader, &aResult->mShiftState) &&
ReadParam(aReader, &aResult->mSkipIfEarlierHandlerDisabled);
}
};

View file

@ -1,6 +1,9 @@
[DEFAULT]
skip-if = os == 'andriod'
[browser_test_AZERTY_digit_shortcut.js]
skip-if =
os == "linux" # Linux build has not implemented sendNativeKeyEvent yet
[browser_test_ContentCache.js]
[browser_test_InputContextURI.js]
[browser_test_clipboardcache.js]

View file

@ -0,0 +1,84 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function () {
let tabs = [];
for (let i = 0; i < 10; i++) {
const tab = BrowserTestUtils.addTab(gBrowser);
tabs.push(tab);
}
const kIsMac = AppConstants.platform == "macosx";
await BrowserTestUtils.withNewTab(
"https://example.com/browser/toolkit/content/tests/browser/file_empty.html",
async function (browser) {
let NativeKeyConstants = {};
Services.scriptloader.loadSubScript(
"chrome://mochikit/content/tests/SimpleTest/NativeKeyCodes.js",
NativeKeyConstants
);
function promiseSynthesizeAccelHyphenMinusWithAZERTY() {
return new Promise(resolve =>
EventUtils.synthesizeNativeKey(
EventUtils.KEYBOARD_LAYOUT_FRENCH_PC,
kIsMac
? NativeKeyConstants.MAC_VK_ANSI_6
: NativeKeyConstants.WIN_VK_6,
{ accelKey: true },
kIsMac ? "-" : "",
kIsMac ? "-" : "",
resolve
)
);
}
async function waitForCondition(aFunc) {
for (let i = 0; i < 60; i++) {
await new Promise(resolve =>
requestAnimationFrame(() => requestAnimationFrame(resolve))
);
if (aFunc(ZoomManager.getFullZoomForBrowser(browser))) {
return true;
}
}
return false;
}
const minZoomLevel = ZoomManager.MIN;
while (true) {
const currentZoom = ZoomManager.getFullZoomForBrowser(browser);
if (minZoomLevel == currentZoom) {
break;
}
info(`Trying to zoom out: ${currentZoom}`);
await promiseSynthesizeAccelHyphenMinusWithAZERTY();
if (!(await waitForCondition(aZoomLevel => aZoomLevel < currentZoom))) {
ok(false, `Failed to zoom out from ${currentZoom}`);
return;
}
}
await promiseSynthesizeAccelHyphenMinusWithAZERTY();
await waitForCondition(() => false);
is(
gBrowser.selectedBrowser,
browser,
"Tab shouldn't be changed by Ctrl+- of AZERTY keyboard layout"
);
// Reset the zoom before going to the next test.
EventUtils.synthesizeKey("0", { accelKey: true });
await waitForCondition(aZoomLevel => aZoomLevel == 1);
}
);
while (tabs.length) {
await new Promise(resolve => {
const tab = tabs.shift();
BrowserTestUtils.waitForTabClosing(tab).then(resolve);
BrowserTestUtils.removeTab(tab);
});
}
});