Bug 865649 part.1 Implement KeyboardEvent.code r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Sun, 25 May 2014 11:08:58 +0900
changeset 205166 944b88892f77c0a7a5b6c058625b70e602f7d39e
parent 205165 e6a4624d247f20c30a5088b15b8ae469353d0df4
child 205167 d9eedf819c0de64a6b1ba50ceae981c61b47ec87
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs865649
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 865649 part.1 Implement KeyboardEvent.code r=smaug
dom/events/KeyboardEvent.cpp
dom/events/KeyboardEvent.h
dom/events/PhysicalKeyCodeNameList.h
dom/events/moz.build
dom/events/test/test_dom_keyboard_event.html
dom/events/test/test_eventctors.html
dom/webidl/KeyboardEvent.webidl
modules/libpref/src/init/all.js
widget/EventForwards.h
widget/TextEvents.h
widget/nsGUIEventIPC.h
widget/shared/NativeKeyToDOMCodeName.h
widget/shared/WidgetEventImpl.cpp
--- a/dom/events/KeyboardEvent.cpp
+++ b/dom/events/KeyboardEvent.cpp
@@ -125,16 +125,22 @@ KeyboardEvent::GetModifierState(const ns
 
 NS_IMETHODIMP
 KeyboardEvent::GetKey(nsAString& aKeyName)
 {
   mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName);
   return NS_OK;
 }
 
+void
+KeyboardEvent::GetCode(nsAString& aCodeName)
+{
+  mEvent->AsKeyboardEvent()->GetDOMCodeName(aCodeName);
+}
+
 NS_IMETHODIMP
 KeyboardEvent::GetCharCode(uint32_t* aCharCode)
 {
   NS_ENSURE_ARG_POINTER(aCharCode);
   *aCharCode = CharCode();
   return NS_OK;
 }
 
@@ -244,16 +250,18 @@ KeyboardEvent::Constructor(const GlobalO
   newEvent->mInitialzedWhichValue = aParam.mWhich;
 
   WidgetKeyboardEvent* internalEvent = newEvent->mEvent->AsKeyboardEvent();
   internalEvent->location = aParam.mLocation;
   internalEvent->mIsRepeat = aParam.mRepeat;
   internalEvent->mIsComposing = aParam.mIsComposing;
   internalEvent->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
   internalEvent->mKeyValue = aParam.mKey;
+  internalEvent->mCodeNameIndex = CODE_NAME_INDEX_USE_STRING;
+  internalEvent->mCodeValue = aParam.mCode;
 
   return newEvent.forget();
 }
 
 NS_IMETHODIMP
 KeyboardEvent::InitKeyEvent(const nsAString& aType,
                             bool aCanBubble,
                             bool aCancelable,
--- a/dom/events/KeyboardEvent.h
+++ b/dom/events/KeyboardEvent.h
@@ -53,16 +53,18 @@ public:
 
   bool Repeat();
   bool IsComposing();
   uint32_t CharCode();
   uint32_t KeyCode();
   virtual uint32_t Which() MOZ_OVERRIDE;
   uint32_t Location();
 
+  void GetCode(nsAString& aCode);
+
   void InitKeyEvent(const nsAString& aType, bool aCanBubble, bool aCancelable,
                     nsIDOMWindow* aView, bool aCtrlKey, bool aAltKey,
                     bool aShiftKey, bool aMetaKey,
                     uint32_t aKeyCode, uint32_t aCharCode,
                     ErrorResult& aRv)
   {
     aRv = InitKeyEvent(aType, aCanBubble, aCancelable, aView,
                        aCtrlKey, aAltKey, aShiftKey,aMetaKey,
new file mode 100644
--- /dev/null
+++ b/dom/events/PhysicalKeyCodeNameList.h
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This header file defines all DOM code name which are used for DOM
+ * KeyboardEvent.code.
+ * You must define NS_DEFINE_PHYSICAL_KEY_CODE_NAME macro before including this.
+ *
+ * It must have two arguments, (aCPPName, aDOMCodeName)
+ * aCPPName is usable name for a part of C++ constants.
+ * aDOMCodeName is the actual value.
+ */
+
+#define NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL(aCPPName, aDOMCodeName) \
+  NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName)
+
+#define DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(aName) \
+  NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL(aName, #aName)
+
+// Unknown key
+NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL(UNKNOWN, "")
+
+// Writing system keys
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Backquote)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Backslash)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Backspace)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BracketLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BracketRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Comma)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit0)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit1)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit2)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit3)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit4)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit5)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit6)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit7)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit8)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit9)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Equal)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlBackslash)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlHash)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlRo)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlYen)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyA)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyB)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyC)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyD)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyE)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyF)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyG)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyH)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyI)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyJ)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyK)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyL)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyM)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyN)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyO)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyP)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyQ)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyR)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyS)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyT)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyU)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyV)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyW)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyX)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyY)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyZ)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Minus)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Period)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Quote)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Semicolon)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Slash)
+
+// Functional keys
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(AltLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(AltRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(CapsLock)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ContextMenu)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ControlLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ControlRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Enter)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(OSLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(OSRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ShiftLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ShiftRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Space)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Tab)
+
+// IME keys
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Convert)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KanaMode)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang1)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang2)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang3)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang4)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang5)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NonConvert)
+
+// Control pad section
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Delete)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(End)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Help)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Home)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Insert)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PageDown)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PageUp)
+
+// Arrow pad section
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ArrowDown)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ArrowLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ArrowRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ArrowUp)
+
+// Numpad section
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumLock)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad0)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad1)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad2)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad3)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad4)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad5)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad6)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad7)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad8)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad9)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadAdd)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadBackspace)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClear)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClearEntry)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadComma)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDecimal)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDivide)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEnter)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEqual)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryAdd)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryClear)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryRecall)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryStore)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemorySubtract)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMultiply)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenLeft)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenRight)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadSubtract)
+
+// Function section
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Escape)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F1)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F2)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F3)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F4)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F5)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F6)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F7)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F8)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F9)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F10)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F11)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F12)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F13)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F14)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F15)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F16)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F17)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F18)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F19)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F20)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F21)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F22)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F23)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F24)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Fn)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PrintScreen)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ScrollLock)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Pause)
+
+// Media keys
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserBack)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserFavorites)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserForward)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserHome)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserRefresh)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserSearch)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserStop)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Eject)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(LaunchApp1)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(LaunchApp2)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(LaunchMail)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(MediaPlayPause)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(MediaSelect)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(MediaStop)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(MediaTrackNext)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(MediaTrackPrevious)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Power)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Sleep)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeDown)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeMute)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeUp)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(WakeUp)
+
+// Legacy keys
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Abort)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Hyper)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Meta)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Resume)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Super)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Suspend)
+DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Turbo)
+
+#undef DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME
+#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -20,16 +20,17 @@ EXPORTS.mozilla += [
     'EventListenerManager.h',
     'EventNameList.h',
     'EventStateManager.h',
     'EventStates.h',
     'IMEStateManager.h',
     'InternalMutationEvent.h',
     'JSEventHandler.h',
     'KeyNameList.h',
+    'PhysicalKeyCodeNameList.h',
     'TextComposition.h',
     'VirtualKeyCodeList.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'AnimationEvent.h',
     'BeforeUnloadEvent.h',
     'ClipboardEvent.h',
--- a/dom/events/test/test_dom_keyboard_event.html
+++ b/dom/events/test/test_dom_keyboard_event.html
@@ -9,16 +9,18 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+var gCodeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled");
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(runTests, window);
 
 function testInitializingUntrustedEvent()
 {
   const kTests = [
     { createEventArg: "KeyboardEvent",
       type: "keydown", bubbles: true, cancelable: true, view: null,
@@ -117,18 +119,21 @@ function testInitializingUntrustedEvent(
           }
         }
       } else {
         is(e[attr], kTest[attr], description + attr + " returns wrong value");
       }
     }
     is(e.isTrusted, false, description + "isTrusted returns wrong value");
 
-    // Currently, there is no way to initialize char and key attribute values.
-    ok(e.key === "", description + "key must return empty string - got " + e.key);
+    // key and code values cannot be initialized with initKeyEvent().
+    is(e.key, "", description + "key must return empty string");
+    if (gCodeEnabled) {
+      is(e.code, "", description + "code must be empty string");
+    }
 
     // getModifierState() tests
     is(e.getModifierState("Shift"), kTest.shiftKey,
        description + "getModifierState(\"Shift\") returns wrong value");
     is(e.getModifierState("Control"), kTest.ctrlKey,
        description + "getModifierState(\"Control\") returns wrong value");
     is(e.getModifierState("Alt"), kTest.altKey,
        description + "getModifierState(\"Alt\") returns wrong value");
--- a/dom/events/test/test_eventctors.html
+++ b/dom/events/test/test_eventctors.html
@@ -360,16 +360,17 @@ is(receivedEvent, e, "KeyboardEvent: Wro
 
 var keyboardEventProps =
 [
   { bubbles: false },
   { cancelable: false },
   { view: null },
   { detail: 0 },
   { key: "" },
+  { code: "" },
   { location: 0 },
   { ctrlKey: false },
   { shiftKey: false },
   { altKey: false },
   { metaKey: false },
   { repeat: false },
   { isComposing: false },
   { charCode: 0 },
@@ -379,44 +380,52 @@ var keyboardEventProps =
 
 var testKeyboardProps =
 [
   { bubbles: true },
   { cancelable: true },
   { view: window },
   { detail: 1 },
   { key: "CustomKey" },
+  { code: "CustomCode" },
   { location: 1 },
   { ctrlKey: true },
   { shiftKey: true },
   { altKey: true },
   { metaKey: true },
   { repeat: true },
   { isComposing: true },
   { charCode: 2 },
   { keyCode: 3 },
   { which: 4 },
   { charCode: 5, which: 6 },
   { keyCode: 7, which: 8 },
   { keyCode: 9, charCode: 10 },
   { keyCode: 11, charCode: 12, which: 13 },
 ];
 
+var codeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled");
 var defaultKeyboardEventValues = {};
 for (var i = 0; i < keyboardEventProps.length; ++i) {
   for (prop in keyboardEventProps[i]) {
+    if (!codeEnabled && prop == "code") {
+      continue;
+    }
     ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
     defaultKeyboardEventValues[prop] = keyboardEventProps[i][prop]; 
   }
 }
 
 while (testKeyboardProps.length) {
   var p = testKeyboardProps.shift();
   e = new KeyboardEvent("foo", p);
   for (var def in defaultKeyboardEventValues) {
+    if (!codeEnabled && def == "code") {
+      continue;
+    }
     if (!(def in p)) {
       is(e[def], defaultKeyboardEventValues[def],
          "KeyboardEvent: Wrong default value for " + def + "!");
     } else {
       is(e[def], p[def],
          "KeyboardEvent: Wrong event init value for " + def + "!");
     }
   }
--- a/dom/webidl/KeyboardEvent.webidl
+++ b/dom/webidl/KeyboardEvent.webidl
@@ -26,21 +26,24 @@ interface KeyboardEvent : UIEvent
   const unsigned long DOM_KEY_LOCATION_MOBILE   = 0x04;
   const unsigned long DOM_KEY_LOCATION_JOYSTICK = 0x05;
 
   readonly attribute unsigned long location;
   readonly attribute boolean       repeat;
   readonly attribute boolean       isComposing;
 
   readonly attribute DOMString key;
+  [Pref="dom.keyboardevent.code.enabled"]
+  readonly attribute DOMString code;
 };
 
 dictionary KeyboardEventInit : UIEventInit
 {
   DOMString      key           = "";
+  DOMString      code          = "";
   unsigned long  location      = 0;
   boolean        ctrlKey       = false;
   boolean        shiftKey      = false;
   boolean        altKey        = false;
   boolean        metaKey       = false;
   boolean        repeat        = false;
   boolean        isComposing   = false;
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -116,16 +116,23 @@ pref("dom.enable_resource_timing", false
 // Whether the Gamepad API is enabled
 pref("dom.gamepad.enabled", true);
 #ifdef RELEASE_BUILD
 pref("dom.gamepad.non_standard_events.enabled", false);
 #else
 pref("dom.gamepad.non_standard_events.enabled", true);
 #endif
 
+// Whether the KeyboardEvent.code is enabled
+#ifdef RELEASE_BUILD
+pref("dom.keyboardevent.code.enabled", false);
+#else
+pref("dom.keyboardevent.code.enabled", true);
+#endif
+
 // Whether the WebCrypto API is enabled
 #ifdef RELEASE_BUILD
 pref("dom.webcrypto.enabled", false);
 #else
 pref("dom.webcrypto.enabled", true);
 #endif
 
 // Whether the UndoManager API is enabled
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -40,16 +40,29 @@ enum KeyNameIndex
 #include "mozilla/KeyNameList.h"
   // If a DOM keyboard event is synthesized by script, this is used.  Then,
   // specified key name should be stored and use it as .key value.
   KEY_NAME_INDEX_USE_STRING
 };
 
 #undef NS_DEFINE_KEYNAME
 
+#define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
+  CODE_NAME_INDEX_##aCPPName,
+
+enum CodeNameIndex
+{
+#include "mozilla/PhysicalKeyCodeNameList.h"
+  // If a DOM keyboard event is synthesized by script, this is used.  Then,
+  // specified code name should be stored and use it as .code value.
+  CODE_NAME_INDEX_USE_STRING
+};
+
+#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
+
 #define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName
 
 typedef int8_t CommandInt;
 enum Command MOZ_ENUM_TYPE(CommandInt)
 {
   CommandDoNothing
 
 #include "mozilla/CommandList.h"
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -82,16 +82,17 @@ public:
     : WidgetInputEvent(aIsTrusted, aMessage, aWidget, NS_KEY_EVENT)
     , keyCode(0)
     , charCode(0)
     , location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD)
     , isChar(false)
     , mIsRepeat(false)
     , mIsComposing(false)
     , mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
+    , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
     , mNativeKeyEvent(nullptr)
     , mUniqueId(0)
   {
   }
 
   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   {
     MOZ_ASSERT(eventStructType == NS_KEY_EVENT,
@@ -123,53 +124,70 @@ public:
   // if this is keyup event, always false.
   bool mIsRepeat;
   // Indicates whether the event is generated during IME (or deadkey)
   // composition.  This is initialized by EventStateManager.  So, key event
   // dispatchers don't need to initialize this.
   bool mIsComposing;
   // DOM KeyboardEvent.key
   KeyNameIndex mKeyNameIndex;
+  // DOM KeyboardEvent.code
+  CodeNameIndex mCodeNameIndex;
   // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
   nsString mKeyValue;
+  // DOM KeyboardEvent.code only when mCodeNameIndex is
+  // CODE_NAME_INDEX_USE_STRING.
+  nsString mCodeValue;
   // OS-specific native event can optionally be preserved
   void* mNativeKeyEvent;
   // Unique id associated with a keydown / keypress event. Used in identifing
   // keypress events for removal from async event dispatch queue in metrofx
   // after preventDefault is called on keydown events. It's ok if this wraps
   // over long periods.
   uint32_t mUniqueId;
 
   void GetDOMKeyName(nsAString& aKeyName)
   {
     if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
       aKeyName = mKeyValue;
       return;
     }
     GetDOMKeyName(mKeyNameIndex, aKeyName);
   }
+  void GetDOMCodeName(nsAString& aCodeName)
+  {
+    if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
+      aCodeName = mCodeValue;
+      return;
+    }
+    GetDOMCodeName(mCodeNameIndex, aCodeName);
+  }
 
-  static void GetDOMKeyName(mozilla::KeyNameIndex aKeyNameIndex,
+  static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
                             nsAString& aKeyName);
+  static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
+                             nsAString& aCodeName);
 
   static const char* GetCommandStr(Command aCommand);
 
   void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
   {
     AssignInputEventData(aEvent, aCopyTargets);
 
     keyCode = aEvent.keyCode;
     charCode = aEvent.charCode;
     location = aEvent.location;
     alternativeCharCodes = aEvent.alternativeCharCodes;
     isChar = aEvent.isChar;
     mIsRepeat = aEvent.mIsRepeat;
     mIsComposing = aEvent.mIsComposing;
     mKeyNameIndex = aEvent.mKeyNameIndex;
+    mCodeNameIndex = aEvent.mCodeNameIndex;
     mKeyValue = aEvent.mKeyValue;
+    mCodeValue = aEvent.mCodeValue;
     // Don't copy mNativeKeyEvent because it may be referred after its instance
     // is destroyed.
     mNativeKeyEvent = nullptr;
     mUniqueId = aEvent.mUniqueId;
   }
 };
 
 /******************************************************************************
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -292,42 +292,48 @@ template<>
 struct ParamTraits<mozilla::WidgetKeyboardEvent>
 {
   typedef mozilla::WidgetKeyboardEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetInputEvent>(aParam));
     WriteParam(aMsg, static_cast<uint32_t>(aParam.mKeyNameIndex));
+    WriteParam(aMsg, static_cast<uint32_t>(aParam.mCodeNameIndex));
     WriteParam(aMsg, aParam.mKeyValue);
+    WriteParam(aMsg, aParam.mCodeValue);
     WriteParam(aMsg, aParam.keyCode);
     WriteParam(aMsg, aParam.charCode);
     WriteParam(aMsg, aParam.isChar);
     WriteParam(aMsg, aParam.mIsRepeat);
     WriteParam(aMsg, aParam.location);
     WriteParam(aMsg, aParam.mUniqueId);
     // An OS-specific native event might be attached in |mNativeKeyEvent|,  but
     // that cannot be copied across process boundaries.
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
-    uint32_t keyNameIndex = 0;
+    uint32_t keyNameIndex = 0, codeNameIndex = 0;
     if (ReadParam(aMsg, aIter,
                   static_cast<mozilla::WidgetInputEvent*>(aResult)) &&
         ReadParam(aMsg, aIter, &keyNameIndex) &&
+        ReadParam(aMsg, aIter, &codeNameIndex) &&
         ReadParam(aMsg, aIter, &aResult->mKeyValue) &&
+        ReadParam(aMsg, aIter, &aResult->mCodeValue) &&
         ReadParam(aMsg, aIter, &aResult->keyCode) &&
         ReadParam(aMsg, aIter, &aResult->charCode) &&
         ReadParam(aMsg, aIter, &aResult->isChar) &&
         ReadParam(aMsg, aIter, &aResult->mIsRepeat) &&
         ReadParam(aMsg, aIter, &aResult->location) &&
         ReadParam(aMsg, aIter, &aResult->mUniqueId))
     {
       aResult->mKeyNameIndex = static_cast<mozilla::KeyNameIndex>(keyNameIndex);
+      aResult->mCodeNameIndex =
+        static_cast<mozilla::CodeNameIndex>(codeNameIndex);
       aResult->mNativeKeyEvent = nullptr;
       return true;
     }
     return false;
   }
 };
 
 template<>
new file mode 100644
--- /dev/null
+++ b/widget/shared/NativeKeyToDOMCodeName.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This header file defines simple code mapping between native scancode or
+ * something and DOM code name index.
+ * You must define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX macro before include
+ * this.
+ *
+ * It must have two arguments, (aNativeKey, aCodeNameIndex).
+ * aNativeKey is a scancode value or something (depends on the platform).
+ * aCodeNameIndex is the widget::CodeNameIndex value.
+ */
+
+// Windows
+#define CODE_MAP_WIN(aCPPCodeName, aNativeKey)
+// Mac OS X
+#define CODE_MAP_MAC(aCPPCodeName, aNativeKey)
+// GTK and Qt on Linux
+#define CODE_MAP_X11(aCPPCodeName, aNativeKey)
+// Android and Gonk
+#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey)
+
+#if defined(XP_WIN)
+#undef CODE_MAP_WIN
+#define CODE_MAP_WIN(aCPPCodeName, aNativeKey) \
+  NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
+                                       CODE_NAME_INDEX_##aCPPCodeName)
+#elif defined(XP_MACOSX)
+#undef CODE_MAP_MAC
+#define CODE_MAP_MAC(aCPPCodeName, aNativeKey) \
+  NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
+                                       CODE_NAME_INDEX_##aCPPCodeName)
+#elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
+#undef CODE_MAP_X11
+#define CODE_MAP_X11(aCPPCodeName, aNativeKey) \
+  NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
+                                       CODE_NAME_INDEX_##aCPPCodeName)
+#elif defined(ANDROID)
+#undef CODE_MAP_ANDROID
+#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey) \
+  NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
+                                       CODE_NAME_INDEX_##aCPPCodeName)
+#endif
+
+// TODO: Define the mapping table.
+
+#undef CODE_MAP_WIN
+#undef CODE_MAP_MAC
+#undef CODE_MAP_X11
+#undef CODE_MAP_ANDROID
--- a/widget/shared/WidgetEventImpl.cpp
+++ b/widget/shared/WidgetEventImpl.cpp
@@ -345,16 +345,39 @@ WidgetKeyboardEvent::GetDOMKeyName(KeyNa
 
   // Subtract off 1 for the null terminator.
   aKeyName.Assign(table + offset, nextOffset - offset - 1);
 
 #undef KEY_STR_NUM
 #undef KEY_STR_NUM_INTERNAL
 }
 
+/*static*/ void
+WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
+                                    nsAString& aCodeName)
+{
+  if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
+    aCodeName.Truncate();
+    return;
+  }
+
+#define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
+    MOZ_UTF16(aDOMCodeName),
+  static const char16_t* kCodeNames[] = {
+#include "mozilla/PhysicalKeyCodeNameList.h"
+    MOZ_UTF16("")
+  };
+#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
+
+  MOZ_RELEASE_ASSERT(static_cast<size_t>(aCodeNameIndex) <
+                       ArrayLength(kCodeNames),
+                     "Illegal physical code enumeration value");
+  aCodeName = kCodeNames[aCodeNameIndex];
+}
+
 /* static */ const char*
 WidgetKeyboardEvent::GetCommandStr(Command aCommand)
 {
 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
   static const char* kCommands[] = {
     "" // CommandDoNothing
 #include "mozilla/CommandList.h"
   };