Bug 920425 part.18 Use mozilla::WidgetEvent::AsKeyboardEvent() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 18 Oct 2013 15:10:24 +0900
changeset 165129 1ac236b84f070245e7909dee2140c1b7499af9ae
parent 165128 ea4c8fcc6d8f7eabac4a408f3ecd8be2a2143127
child 165130 c8e43d3e128d3b0bf99280cec145c7b68fbf19aa
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs920425
milestone27.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 920425 part.18 Use mozilla::WidgetEvent::AsKeyboardEvent() r=smaug
content/base/public/nsContentUtils.h
content/base/src/Element.cpp
content/base/src/nsContentUtils.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMKeyboardEvent.cpp
content/events/src/nsDOMKeyboardEvent.h
content/events/src/nsDOMUIEvent.cpp
content/events/src/nsEventDispatcher.cpp
content/events/src/nsEventStateManager.cpp
content/html/content/src/HTMLButtonElement.cpp
content/html/content/src/HTMLInputElement.cpp
content/html/content/src/nsTextEditorState.cpp
content/xbl/src/nsXBLWindowKeyHandler.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/forms/nsListControlFrame.cpp
layout/xul/base/src/nsButtonBoxFrame.cpp
layout/xul/base/src/nsMenuBarFrame.cpp
layout/xul/base/src/nsMenuBarListener.cpp
layout/xul/base/src/nsMenuFrame.cpp
widget/cocoa/nsChildView.mm
widget/windows/winrt/MetroWidget.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1364,23 +1364,16 @@ public:
   static nsIWidget* GetTopLevelWidget(nsIWidget* aWidget);
 
   /**
    * Return the localized ellipsis for UI.
    */
   static const nsDependentString GetLocalizedEllipsis();
 
   /**
-   * The routine GetNativeEvent returns the result of
-   * aDOMEvent->GetInternalNSEvent().
-   * XXX Is this necessary?
-   */
-  static mozilla::WidgetEvent* GetNativeEvent(nsIDOMEvent* aDOMEvent);
-
-  /**
    * Get the candidates for accelkeys for aDOMKeyEvent.
    *
    * @param aDOMKeyEvent [in] the key event for accelkey handling.
    * @param aCandidates [out] the candidate shortcut key combination list.
    *                          the first item is most preferred.
    */
   static void GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
                                     nsTArray<nsShortcutCandidate>& aCandidates);
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -2282,26 +2282,23 @@ Element::PostHandleEventForLinks(nsEvent
                                     aVisitor.mEvent->mFlags.mIsTrusted);
         aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
       }
     }
     break;
 
   case NS_KEY_PRESS:
     {
-      if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
-        WidgetKeyboardEvent* keyEvent =
-          static_cast<WidgetKeyboardEvent*>(aVisitor.mEvent);
-        if (keyEvent->keyCode == NS_VK_RETURN) {
-          nsEventStatus status = nsEventStatus_eIgnore;
-          rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
-                                  false, nullptr, &status);
-          if (NS_SUCCEEDED(rv)) {
-            aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
-          }
+      WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
+      if (keyEvent && keyEvent->keyCode == NS_VK_RETURN) {
+        nsEventStatus status = nsEventStatus_eIgnore;
+        rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
+                                false, nullptr, &status);
+        if (NS_SUCCEEDED(rv)) {
+          aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
         }
       }
     }
     break;
 
   default:
     // switch not in sync with the optimization switch earlier in this function
     NS_NOTREACHED("switch statements not in sync");
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -4552,23 +4552,16 @@ nsContentUtils::GetLocalizedEllipsis()
                           uint32_t(ArrayLength(sBuf) - 1));
     CopyUnicodeTo(tmp, 0, sBuf, len);
     if (!sBuf[0])
       sBuf[0] = PRUnichar(0x2026);
   }
   return nsDependentString(sBuf);
 }
 
-//static
-WidgetEvent*
-nsContentUtils::GetNativeEvent(nsIDOMEvent* aDOMEvent)
-{
-  return aDOMEvent ? aDOMEvent->GetInternalNSEvent() : nullptr;
-}
-
 static bool
 HasASCIIDigit(const nsTArray<nsShortcutCandidate>& aCandidates)
 {
   for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
     uint32_t ch = aCandidates[i].mCharCode;
     if (ch >= '0' && ch <= '9')
       return true;
   }
@@ -4599,17 +4592,17 @@ nsContentUtils::GetAccelKeyCandidates(ns
 
   nsAutoString eventType;
   aDOMKeyEvent->GetType(eventType);
   // Don't process if aDOMKeyEvent is not a keypress event.
   if (!eventType.EqualsLiteral("keypress"))
     return;
 
   WidgetKeyboardEvent* nativeKeyEvent =
-    static_cast<WidgetKeyboardEvent*>(GetNativeEvent(aDOMKeyEvent));
+    aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   if (nativeKeyEvent) {
     NS_ASSERTION(nativeKeyEvent->eventStructType == NS_KEY_EVENT,
                  "wrong type of native event");
     // nsShortcutCandidate::mCharCode is a candidate charCode.
     // nsShoftcutCandidate::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.
     // the priority of the charCodes are (shift key is not pressed):
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -530,18 +530,17 @@ nsDOMEvent::DuplicatePrivateData()
       WidgetInputEvent* oldInputEvent = static_cast<WidgetInputEvent*>(mEvent);
       WidgetInputEvent* inputEvent = new WidgetInputEvent(false, msg, nullptr);
       inputEvent->AssignInputEventData(*oldInputEvent, true);
       newEvent = inputEvent;
       break;
     }
     case NS_KEY_EVENT:
     {
-      WidgetKeyboardEvent* oldKeyEvent =
-        static_cast<WidgetKeyboardEvent*>(mEvent);
+      WidgetKeyboardEvent* oldKeyEvent = mEvent->AsKeyboardEvent();
       WidgetKeyboardEvent* keyEvent =
         new WidgetKeyboardEvent(false, msg, nullptr);
       keyEvent->AssignKeyEventData(*oldKeyEvent, true);
       newEvent = keyEvent;
       break;
     }
     case NS_MOUSE_EVENT:
     {
@@ -881,17 +880,17 @@ nsDOMEvent::GetEventPopupControlState(Wi
       case NS_XUL_COMMAND:
         abuse = openControlled;
         break;
       }
     }
     break;
   case NS_KEY_EVENT :
     if (aEvent->mFlags.mIsTrusted) {
-      uint32_t key = static_cast<WidgetKeyboardEvent*>(aEvent)->keyCode;
+      uint32_t key = aEvent->AsKeyboardEvent()->keyCode;
       switch(aEvent->message) {
       case NS_KEY_PRESS :
         // return key on focused button. see note at NS_MOUSE_CLICK.
         if (key == nsIDOMKeyEvent::DOM_VK_RETURN)
           abuse = openAllowed;
         else if (::PopupAllowedForEvent("keypress"))
           abuse = openControlled;
         break;
--- a/content/events/src/nsDOMKeyboardEvent.cpp
+++ b/content/events/src/nsDOMKeyboardEvent.cpp
@@ -74,17 +74,17 @@ nsDOMKeyboardEvent::GetModifierState(con
   *aState = GetModifierState(aKey);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetKey(nsAString& aKeyName)
 {
   if (!mEventIsInternal) {
-    static_cast<WidgetKeyboardEvent*>(mEvent)->GetDOMKeyName(aKeyName);
+    mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetCharCode(uint32_t* aCharCode)
 {
   NS_ENSURE_ARG_POINTER(aCharCode);
@@ -95,17 +95,17 @@ nsDOMKeyboardEvent::GetCharCode(uint32_t
 uint32_t
 nsDOMKeyboardEvent::CharCode()
 {
   switch (mEvent->message) {
   case NS_KEY_UP:
   case NS_KEY_DOWN:
     return 0;
   case NS_KEY_PRESS:
-    return static_cast<WidgetKeyboardEvent*>(mEvent)->charCode;
+    return mEvent->AsKeyboardEvent()->charCode;
   }
   return 0;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetKeyCode(uint32_t* aKeyCode)
 {
   NS_ENSURE_ARG_POINTER(aKeyCode);
@@ -115,33 +115,33 @@ nsDOMKeyboardEvent::GetKeyCode(uint32_t*
 
 uint32_t
 nsDOMKeyboardEvent::KeyCode()
 {
   switch (mEvent->message) {
   case NS_KEY_UP:
   case NS_KEY_PRESS:
   case NS_KEY_DOWN:
-    return static_cast<WidgetKeyboardEvent*>(mEvent)->keyCode;
+    return mEvent->AsKeyboardEvent()->keyCode;
   }
   return 0;
 }
 
 uint32_t
 nsDOMKeyboardEvent::Which()
 {
   switch (mEvent->message) {
     case NS_KEY_UP:
     case NS_KEY_DOWN:
       return KeyCode();
     case NS_KEY_PRESS:
       //Special case for 4xp bug 62878.  Try to make value of which
       //more closely mirror the values that 4.x gave for RETURN and BACKSPACE
       {
-        uint32_t keyCode = static_cast<WidgetKeyboardEvent*>(mEvent)->keyCode;
+        uint32_t keyCode = mEvent->AsKeyboardEvent()->keyCode;
         if (keyCode == NS_VK_RETURN || keyCode == NS_VK_BACK) {
           return keyCode;
         }
         return CharCode();
       }
   }
 
   return 0;
@@ -151,26 +151,32 @@ NS_IMETHODIMP
 nsDOMKeyboardEvent::GetLocation(uint32_t* aLocation)
 {
   NS_ENSURE_ARG_POINTER(aLocation);
 
   *aLocation = Location();
   return NS_OK;
 }
 
+uint32_t
+nsDOMKeyboardEvent::Location()
+{
+  return mEvent->AsKeyboardEvent()->location;
+}
+
 NS_IMETHODIMP
 nsDOMKeyboardEvent::InitKeyEvent(const nsAString& aType, bool aCanBubble, bool aCancelable,
                                  nsIDOMWindow* aView, bool aCtrlKey, bool aAltKey,
                                  bool aShiftKey, bool aMetaKey,
                                  uint32_t aKeyCode, uint32_t aCharCode)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(mEvent);
+  WidgetKeyboardEvent* keyEvent = mEvent->AsKeyboardEvent();
   keyEvent->InitBasicModifiers(aCtrlKey, aAltKey, aShiftKey, aMetaKey);
   keyEvent->keyCode = aKeyCode;
   keyEvent->charCode = aCharCode;
 
   return NS_OK;
 }
 
 nsresult NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
--- a/content/events/src/nsDOMKeyboardEvent.h
+++ b/content/events/src/nsDOMKeyboardEvent.h
@@ -5,17 +5,17 @@
 
 #ifndef nsDOMKeyboardEvent_h__
 #define nsDOMKeyboardEvent_h__
 
 #include "nsIDOMKeyEvent.h"
 #include "nsDOMUIEvent.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/BasicEvents.h"
 
 class nsDOMKeyboardEvent : public nsDOMUIEvent,
                            public nsIDOMKeyEvent
 {
 public:
   nsDOMKeyboardEvent(mozilla::dom::EventTarget* aOwner,
                      nsPresContext* aPresContext,
                      mozilla::WidgetKeyboardEvent* aEvent);
@@ -57,21 +57,17 @@ public:
   bool GetModifierState(const nsAString& aKey)
   {
     return GetModifierStateInternal(aKey);
   }
 
   uint32_t CharCode();
   uint32_t KeyCode();
   virtual uint32_t Which() MOZ_OVERRIDE;
-
-  uint32_t Location()
-  {
-    return static_cast<mozilla::WidgetKeyboardEvent*>(mEvent)->location;
-  }
+  uint32_t Location();
 
   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,
                     mozilla::ErrorResult& aRv)
   {
     aRv = InitKeyEvent(aType, aCanBubble, aCancelable, aView,
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -339,26 +339,22 @@ nsDOMUIEvent::GetIsChar(bool* aIsChar)
 {
   *aIsChar = IsChar();
   return NS_OK;
 }
 
 bool
 nsDOMUIEvent::IsChar() const
 {
-  switch (mEvent->eventStructType)
-  {
-    case NS_KEY_EVENT:
-      return static_cast<WidgetKeyboardEvent*>(mEvent)->isChar;
-    case NS_TEXT_EVENT:
-      return static_cast<WidgetTextEvent*>(mEvent)->isChar;
-    default:
-      return false;
+  WidgetKeyboardEvent* keyEvent = mEvent->AsKeyboardEvent();
+  if (keyEvent) {
+    return keyEvent->isChar;
   }
-  MOZ_CRASH("Switch handles all cases.");
+  WidgetTextEvent* textEvent = mEvent->AsTextEvent();
+  return textEvent ? textEvent->isChar : false;
 }
 
 NS_IMETHODIMP
 nsDOMUIEvent::DuplicatePrivateData()
 {
   mClientPoint = nsDOMEvent::GetClientCoords(mPresContext,
                                              mEvent,
                                              mEvent->refPoint,
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -698,17 +698,17 @@ nsEventDispatcher::CreateEvent(mozilla::
     case NS_UI_EVENT:
       return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext,
                               static_cast<WidgetGUIEvent*>(aEvent));
     case NS_SCROLLAREA_EVENT:
       return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext,
                                       aEvent->AsScrollAreaEvent());
     case NS_KEY_EVENT:
       return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext,
-                                    static_cast<WidgetKeyboardEvent*>(aEvent));
+                                    aEvent->AsKeyboardEvent());
     case NS_COMPOSITION_EVENT:
       return NS_NewDOMCompositionEvent(
         aDOMEvent, aOwner,
         aPresContext, static_cast<WidgetCompositionEvent*>(aEvent));
     case NS_MOUSE_EVENT:
       return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext,
                                  static_cast<WidgetInputEvent*>(aEvent));
     case NS_FOCUS_EVENT:
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1140,18 +1140,17 @@ nsEventStateManager::PreHandleEvent(nsPr
     // NS_DRAGDROP_DROP is fired before NS_DRAGDROP_DRAGDROP so send
     // the enter/exit events before NS_DRAGDROP_DROP.
     GenerateDragDropEnterExit(aPresContext,
                               static_cast<WidgetGUIEvent*>(aEvent));
     break;
 
   case NS_KEY_PRESS:
     {
-
-      WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
+      WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
 
       int32_t modifierMask = 0;
       if (keyEvent->IsShift())
         modifierMask |= NS_MODIFIER_SHIFT;
       if (keyEvent->IsControl())
         modifierMask |= NS_MODIFIER_CONTROL;
       if (keyEvent->IsAlt())
         modifierMask |= NS_MODIFIER_ALT;
@@ -1603,18 +1602,17 @@ nsEventStateManager::DispatchCrossProces
   }
 
   switch (aEvent->eventStructType) {
   case NS_MOUSE_EVENT: {
     WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
     return remote->SendRealMouseEvent(*mouseEvent);
   }
   case NS_KEY_EVENT: {
-    WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
-    return remote->SendRealKeyEvent(*keyEvent);
+    return remote->SendRealKeyEvent(*aEvent->AsKeyboardEvent());
   }
   case NS_WHEEL_EVENT: {
     WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(aEvent);
     return remote->SendMouseWheelEvent(*wheelEvent);
   }
   case NS_TOUCH_EVENT: {
     // Let the child process synthesize a mouse event if needed, and
     // ensure we don't synthesize one in this process.
@@ -3635,17 +3633,17 @@ nsEventStateManager::PostHandleEvent(nsP
                               static_cast<WidgetGUIEvent*>(aEvent));
     break;
 
   case NS_KEY_UP:
     break;
 
   case NS_KEY_PRESS:
     if (nsEventStatus_eConsumeNoDefault != *aStatus) {
-      WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
+      WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
       //This is to prevent keyboard scrolling while alt modifier in use.
       if (!keyEvent->IsAlt()) {
         switch(keyEvent->keyCode) {
           case NS_VK_TAB:
           case NS_VK_F6:
             // Handling the tab event after it was sent to content is bad,
             // because to the FocusManager the remote-browser looks like one
             // element, so we would just move the focus to the next element
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -255,18 +255,17 @@ HTMLButtonElement::PostHandleEvent(nsEve
 
   if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
     switch (aVisitor.mEvent->message) {
       case NS_KEY_PRESS:
       case NS_KEY_UP:
         {
           // For backwards compat, trigger buttons with space or enter
           // (bug 25300)
-          WidgetKeyboardEvent* keyEvent =
-            static_cast<WidgetKeyboardEvent*>(aVisitor.mEvent);
+          WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
           if ((keyEvent->keyCode == NS_VK_RETURN &&
                NS_KEY_PRESS == aVisitor.mEvent->message) ||
               (keyEvent->keyCode == NS_VK_SPACE &&
                NS_KEY_UP == aVisitor.mEvent->message)) {
             nsEventStatus status = nsEventStatus_eIgnore;
 
             WidgetMouseEvent event(aVisitor.mEvent->mFlags.mIsTrusted,
                                    NS_MOUSE_CLICK, nullptr,
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3505,19 +3505,17 @@ HTMLInputElement::PostHandleEvent(nsEven
           break;
         }
 
         case NS_KEY_PRESS:
         case NS_KEY_UP:
         {
           // For backwards compat, trigger checks/radios/buttons with
           // space or enter (bug 25300)
-          WidgetKeyboardEvent* keyEvent =
-            static_cast<WidgetKeyboardEvent*>(aVisitor.mEvent);
-
+          WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
           if ((aVisitor.mEvent->message == NS_KEY_PRESS &&
                keyEvent->keyCode == NS_VK_RETURN) ||
               (aVisitor.mEvent->message == NS_KEY_UP &&
                keyEvent->keyCode == NS_VK_SPACE)) {
             switch(mType) {
               case NS_FORM_INPUT_CHECKBOX:
               case NS_FORM_INPUT_RADIO:
               {
@@ -3843,18 +3841,17 @@ HTMLInputElement::PostHandleEventForRang
       // the drag and set our final value (unless someone has called
       // preventDefault() and prevents us getting here).
       FinishRangeThumbDrag(static_cast<WidgetInputEvent*>(aVisitor.mEvent));
       aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
       break;
 
     case NS_KEY_PRESS:
       if (mIsDraggingRange &&
-          static_cast<WidgetKeyboardEvent*>(aVisitor.mEvent)->keyCode ==
-            NS_VK_ESCAPE) {
+          aVisitor.mEvent->AsKeyboardEvent()->keyCode == NS_VK_ESCAPE) {
         CancelRangeThumbDrag();
       }
       break;
 
     case NS_TOUCH_CANCEL:
       if (mIsDraggingRange) {
         CancelRangeThumbDrag();
       }
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -848,18 +848,18 @@ nsTextInputListener::HandleEvent(nsIDOME
   bool isTrusted = false;
   rv = aEvent->GetIsTrusted(&isTrusted);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!isTrusted) {
     return NS_OK;
   }
 
   WidgetKeyboardEvent* keyEvent =
-    static_cast<WidgetKeyboardEvent*>(aEvent->GetInternalNSEvent());
-  if (keyEvent->eventStructType != NS_KEY_EVENT) {
+    aEvent->GetInternalNSEvent()->AsKeyboardEvent();
+  if (!keyEvent) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsINativeKeyBindings *bindings = GetKeyBindings();
   if (bindings) {
     bool handled = false;
     switch (keyEvent->message) {
       case NS_KEY_DOWN:
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -356,20 +356,19 @@ nsXBLWindowKeyHandler::WalkHandlers(nsID
     // get the DOM window we're attached to
     nsCOMPtr<nsIControllers> controllers;
     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(mTarget);
     if (root) {
       root->GetControllers(getter_AddRefs(controllers));
     }
 
     WidgetKeyboardEvent* keyEvent =
-      static_cast<WidgetKeyboardEvent*>(aKeyEvent->GetInternalNSEvent());
-    MOZ_ASSERT(keyEvent->eventStructType == NS_KEY_EVENT,
+      aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+    MOZ_ASSERT(keyEvent,
                "DOM key event's internal event must be WidgetKeyboardEvent");
-
     bool handled = false;
     switch (keyEvent->message) {
       case NS_KEY_PRESS:
         handled = sNativeEditorBindings->KeyPress(*keyEvent,
                                                   DoCommandCallback,
                                                   controllers);
         break;
       case NS_KEY_UP:
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -2330,18 +2330,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
               break;
             case NS_KEY_UP:
               event.type = KeyRelease;
               break;
             }
 #endif
 
 #ifdef MOZ_WIDGET_QT
-          const WidgetKeyboardEvent& keyEvent =
-            static_cast<const WidgetKeyboardEvent&>(anEvent);
+          const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
 
           memset( &event, 0, sizeof(event) );
           event.time = anEvent.time;
 
           QWidget* qWidget = static_cast<QWidget*>(widget->GetNativeData(NS_NATIVE_WINDOW));
 
           if (qWidget)
 #if defined(Q_WS_X11)
@@ -2492,18 +2491,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
             }
             break;
           }
       }
       break;
 
     case NS_KEY_EVENT:
      {
-       const WidgetKeyboardEvent& keyEvent =
-         static_cast<const WidgetKeyboardEvent&>(anEvent);
+       const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
        LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
        // pluginEvent is initialized by nsWindow::InitKeyEvent().
        ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent);
        if (pluginEvent) {
          MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent));
          MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType);
          mInstance->HandleEvent(pluginEvent, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
        }
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -4804,17 +4804,18 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyE
 {
   // NOTE: When you change this method, you should also change:
   //   * editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
   //   * editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
   //
   // And also when you add new key handling, you need to change the subclass's
   // HandleKeyPressEvent()'s switch statement.
 
-  WidgetKeyboardEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
+  WidgetKeyboardEvent* nativeKeyEvent =
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
                "HandleKeyPressEvent gets non-keypress event");
 
   // if we are readonly or disabled, then do nothing.
   if (IsReadonly() || IsDisabled()) {
     // consume backspace for disabled and readonly textfields, to prevent
     // back in history, which could be confusing to users
@@ -5157,26 +5158,16 @@ nsEditor::IsModifiableNode(nsIDOMNode *a
 }
 
 bool
 nsEditor::IsModifiableNode(nsINode *aNode)
 {
   return true;
 }
 
-WidgetKeyboardEvent*
-nsEditor::GetNativeKeyEvent(nsIDOMKeyEvent* aDOMKeyEvent)
-{
-  NS_ENSURE_TRUE(aDOMKeyEvent, nullptr);
-  WidgetEvent* nativeEvent = aDOMKeyEvent->GetInternalNSEvent();
-  NS_ENSURE_TRUE(nativeEvent, nullptr);
-  NS_ENSURE_TRUE(nativeEvent->eventStructType == NS_KEY_EVENT, nullptr);
-  return static_cast<WidgetKeyboardEvent*>(nativeEvent);
-}
-
 already_AddRefed<nsIContent>
 nsEditor::GetFocusedContent()
 {
   nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
   if (!piTarget) {
     return nullptr;
   }
 
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -2,17 +2,16 @@
 /* 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/. */
 
 #ifndef __editor_h__
 #define __editor_h__
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
-#include "mozilla/EventForwards.h"      // for WidgetKeyboardEvent
 #include "mozilla/TypedEnum.h"          // for MOZ_BEGIN_ENUM_CLASS, etc.
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMArray.h"                 // for nsCOMArray
 #include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
 #include "nsCycleCollectionParticipant.h"
 #include "nsEditProperty.h"             // for nsEditProperty, etc
 #include "nsIEditor.h"                  // for nsIEditor::EDirection, etc
 #include "nsIEditorIMESupport.h"        // for NS_DECL_NSIEDITORIMESUPPORT, etc
@@ -400,18 +399,16 @@ protected:
   // unregister and release our event listeners
   virtual void RemoveEventListeners();
 
   /**
    * Return true if spellchecking should be enabled for this editor.
    */
   bool GetDesiredSpellCheckState();
 
-  mozilla::WidgetKeyboardEvent* GetNativeKeyEvent(nsIDOMKeyEvent* aDOMKeyEvent);
-
   bool CanEnableSpellCheck()
   {
     // Check for password/readonly/disabled, which are not spellchecked
     // regardless of DOM. Also, check to see if spell check should be skipped or not.
     return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
   }
 
 public:
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -586,17 +586,18 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
   //   * editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
 
   if (IsReadonly() || IsDisabled()) {
     // When we're not editable, the events are handled on nsEditor, so, we can
     // bypass nsPlaintextEditor.
     return nsEditor::HandleKeyPressEvent(aKeyEvent);
   }
 
-  WidgetKeyboardEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
+  WidgetKeyboardEvent* nativeKeyEvent =
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
     case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -350,17 +350,18 @@ nsPlaintextEditor::HandleKeyPressEvent(n
   // And also when you add new key handling, you need to change the subclass's
   // HandleKeyPressEvent()'s switch statement.
 
   if (IsReadonly() || IsDisabled()) {
     // When we're not editable, the events handled on nsEditor.
     return nsEditor::HandleKeyPressEvent(aKeyEvent);
   }
 
-  WidgetKeyboardEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
+  WidgetKeyboardEvent* nativeKeyEvent =
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
     case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6088,17 +6088,17 @@ PresShell::HandleEvent(nsIFrame* aFrame,
   }
 
   if (aEvent->eventStructType == NS_KEY_EVENT &&
       mDocument && mDocument->EventHandlingSuppressed()) {
     if (aEvent->message == NS_KEY_DOWN) {
       mNoDelayedKeyEvents = true;
     } else if (!mNoDelayedKeyEvents) {
       nsDelayedEvent* event =
-        new nsDelayedKeyEvent(static_cast<WidgetKeyboardEvent*>(aEvent));
+        new nsDelayedKeyEvent(aEvent->AsKeyboardEvent());
       if (!mDelayedEvents.AppendElement(event)) {
         delete event;
       }
     }
     return NS_OK;
   }
 
   nsIFrame* frame = aFrame;
@@ -6674,18 +6674,17 @@ PresShell::HandleEventInternal(WidgetEve
     if (aEvent->mFlags.mIsTrusted) {
       switch (aEvent->message) {
       case NS_KEY_PRESS:
       case NS_KEY_DOWN:
       case NS_KEY_UP: {
         nsIDocument* doc = GetCurrentEventContent() ?
                            mCurrentEventContent->OwnerDoc() : nullptr;
         nsIDocument* fullscreenAncestor = nullptr;
-        if (static_cast<const WidgetKeyboardEvent*>(aEvent)->keyCode ==
-              NS_VK_ESCAPE) {
+        if (aEvent->AsKeyboardEvent()->keyCode == NS_VK_ESCAPE) {
           if ((fullscreenAncestor = nsContentUtils::GetFullscreenAncestor(doc))) {
             // Prevent default action on ESC key press when exiting
             // DOM fullscreen mode. This prevents the browser ESC key
             // handler from stopping all loads in the document, which
             // would cause <video> loads to stop.
             aEvent->mFlags.mDefaultPrevented = true;
             aEvent->mFlags.mOnlyChromeDispatch = true;
 
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -595,21 +595,22 @@ protected:
   };
 
   class nsDelayedKeyEvent : public nsDelayedInputEvent
   {
   public:
     nsDelayedKeyEvent(mozilla::WidgetKeyboardEvent* aEvent) :
       nsDelayedInputEvent()
     {
-      mEvent = new mozilla::WidgetKeyboardEvent(aEvent->mFlags.mIsTrusted,
-                                                aEvent->message,
-                                                aEvent->widget);
-      static_cast<mozilla::WidgetKeyboardEvent*>(mEvent)->
-        AssignKeyEventData(*aEvent, false);
+      mozilla::WidgetKeyboardEvent* keyEvent =
+        new mozilla::WidgetKeyboardEvent(aEvent->mFlags.mIsTrusted,
+                                         aEvent->message,
+                                         aEvent->widget);
+      keyEvent->AssignKeyEventData(*aEvent, false);
+      mEvent = keyEvent;
     }
   };
 
   // Check if aEvent is a mouse event and record the mouse location for later
   // synth mouse moves.
   void RecordMouseLocation(mozilla::WidgetGUIEvent* aEvent);
   class nsSynthMouseMoveEvent MOZ_FINAL : public nsARefreshObserver {
   public:
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -2074,20 +2074,19 @@ nsListControlFrame::KeyDown(nsIDOMEvent*
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return NS_OK;
   }
 
   // Don't check defaultPrevented value because other browsers don't prevent
   // the key navigation of list control even if preventDefault() is called.
 
   const WidgetKeyboardEvent* keyEvent =
-    static_cast<WidgetKeyboardEvent*>(aKeyEvent->GetInternalNSEvent());
-  MOZ_ASSERT(keyEvent, "DOM event must have internal event");
-  MOZ_ASSERT(keyEvent->eventStructType == NS_KEY_EVENT,
-    "The keydown event's internal event struct must be WidgetKeyboardEvent");
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+  MOZ_ASSERT(keyEvent,
+    "DOM event must have WidgetKeyboardEvent for its internal event");
 
   if (keyEvent->IsAlt()) {
     if (keyEvent->keyCode == NS_VK_UP || keyEvent->keyCode == NS_VK_DOWN) {
       DropDownToggleKey(aKeyEvent);
     }
     return NS_OK;
   }
 
@@ -2215,20 +2214,19 @@ nsListControlFrame::KeyPress(nsIDOMEvent
   MOZ_ASSERT(aKeyEvent, "aKeyEvent is null.");
 
   nsEventStates eventStates = mContent->AsElement()->State();
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return NS_OK;
   }
 
   const WidgetKeyboardEvent* keyEvent =
-    static_cast<WidgetKeyboardEvent*>(aKeyEvent->GetInternalNSEvent());
-  MOZ_ASSERT(keyEvent, "DOM event must have internal event");
-  MOZ_ASSERT(keyEvent->eventStructType == NS_KEY_EVENT,
-    "The keydown event's internal event struct must be WidgetKeyboardEvent");
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+  MOZ_ASSERT(keyEvent,
+    "DOM event must have WidgetKeyboardEvent for its internal event");
 
   // Select option with this as the first character
   // XXX Not I18N compliant
 
   // Don't do incremental search if the key event has already consumed.
   if (keyEvent->mFlags.mDefaultPrevented) {
     return NS_OK;
   }
--- a/layout/xul/base/src/nsButtonBoxFrame.cpp
+++ b/layout/xul/base/src/nsButtonBoxFrame.cpp
@@ -50,65 +50,68 @@ nsButtonBoxFrame::HandleEvent(nsPresCont
                               nsEventStatus* aEventStatus)
 {
   NS_ENSURE_ARG_POINTER(aEventStatus);
   if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     return NS_OK;
   }
 
   switch (aEvent->message) {
-    case NS_KEY_DOWN:
-      if (NS_KEY_EVENT == aEvent->eventStructType) {
-        WidgetKeyboardEvent* keyEvent =
-          static_cast<WidgetKeyboardEvent*>(aEvent);
-        if (NS_VK_SPACE == keyEvent->keyCode) {
-          nsEventStateManager *esm = aPresContext->EventStateManager();
-          // :hover:active state
-          esm->SetContentState(mContent, NS_EVENT_STATE_HOVER);
-          esm->SetContentState(mContent, NS_EVENT_STATE_ACTIVE);
+    case NS_KEY_DOWN: {
+      WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
+      if (!keyEvent) {
+        break;
+      }
+      if (NS_VK_SPACE == keyEvent->keyCode) {
+        nsEventStateManager* esm = aPresContext->EventStateManager();
+        // :hover:active state
+        esm->SetContentState(mContent, NS_EVENT_STATE_HOVER);
+        esm->SetContentState(mContent, NS_EVENT_STATE_ACTIVE);
+      }
+      break;
+    }
+
+// On mac, Return fires the default button, not the focused one.
+#ifndef XP_MACOSX
+    case NS_KEY_PRESS: {
+      WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
+      if (!keyEvent) {
+        break;
+      }
+      if (NS_VK_RETURN == keyEvent->keyCode) {
+        nsCOMPtr<nsIDOMXULButtonElement> buttonEl(do_QueryInterface(mContent));
+        if (buttonEl) {
+          MouseClicked(aPresContext, aEvent);
+          *aEventStatus = nsEventStatus_eConsumeNoDefault;
         }
       }
       break;
+    }
+#endif
 
-// On mac, Return fires the defualt button, not the focused one.
-#ifndef XP_MACOSX
-    case NS_KEY_PRESS:
-      if (NS_KEY_EVENT == aEvent->eventStructType) {
-        WidgetKeyboardEvent* keyEvent =
-          static_cast<WidgetKeyboardEvent*>(aEvent);
-        if (NS_VK_RETURN == keyEvent->keyCode) {
-          nsCOMPtr<nsIDOMXULButtonElement> buttonEl(do_QueryInterface(mContent));
-          if (buttonEl) {
-            MouseClicked(aPresContext, aEvent);
-            *aEventStatus = nsEventStatus_eConsumeNoDefault;
-          }
+    case NS_KEY_UP: {
+      WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
+      if (!keyEvent) {
+        break;
+      }
+      if (NS_VK_SPACE == keyEvent->keyCode) {
+        // only activate on keyup if we're already in the :hover:active state
+        NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
+        nsEventStates buttonState = mContent->AsElement()->State();
+        if (buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
+                                     NS_EVENT_STATE_HOVER)) {
+          // return to normal state
+          nsEventStateManager *esm = aPresContext->EventStateManager();
+          esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
+          esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
+          MouseClicked(aPresContext, aEvent);
         }
       }
       break;
-#endif
-
-    case NS_KEY_UP:
-      if (NS_KEY_EVENT == aEvent->eventStructType) {
-        WidgetKeyboardEvent* keyEvent =
-          static_cast<WidgetKeyboardEvent*>(aEvent);
-        if (NS_VK_SPACE == keyEvent->keyCode) {
-          // only activate on keyup if we're already in the :hover:active state
-          NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
-          nsEventStates buttonState = mContent->AsElement()->State();
-          if (buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
-                                       NS_EVENT_STATE_HOVER)) {
-            // return to normal state
-            nsEventStateManager *esm = aPresContext->EventStateManager();
-            esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
-            esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
-            MouseClicked(aPresContext, aEvent);
-          }
-        }
-      }
-      break;
+    }
 
     case NS_MOUSE_CLICK:
       if (aEvent->IsLeftClickEvent()) {
         MouseClicked(aPresContext, aEvent);
       }
       break;
   }
 
--- a/layout/xul/base/src/nsMenuBarFrame.cpp
+++ b/layout/xul/base/src/nsMenuBarFrame.cpp
@@ -177,19 +177,18 @@ GetInsertionPoint(nsIPresShell* aShell, 
 
 nsMenuFrame*
 nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
 {
   uint32_t charCode;
   aKeyEvent->GetCharCode(&charCode);
 
   nsAutoTArray<uint32_t, 10> accessKeys;
-  WidgetEvent* nativeEvent = nsContentUtils::GetNativeEvent(aKeyEvent);
   WidgetKeyboardEvent* nativeKeyEvent =
-    static_cast<WidgetKeyboardEvent*>(nativeEvent);
+    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   if (nativeKeyEvent)
     nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, accessKeys);
   if (accessKeys.IsEmpty() && charCode)
     accessKeys.AppendElement(charCode);
 
   if (accessKeys.IsEmpty())
     return nullptr; // no character was pressed so just return
 
--- a/layout/xul/base/src/nsMenuBarListener.cpp
+++ b/layout/xul/base/src/nsMenuBarListener.cpp
@@ -192,19 +192,18 @@ nsMenuBarListener::KeyPress(nsIDOMEvent*
     if (!preventDefault) {
       nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
       uint32_t keyCode, charCode;
       keyEvent->GetKeyCode(&keyCode);
       keyEvent->GetCharCode(&charCode);
 
       bool hasAccessKeyCandidates = charCode != 0;
       if (!hasAccessKeyCandidates) {
-        WidgetEvent* nativeEvent = nsContentUtils::GetNativeEvent(aKeyEvent);
         WidgetKeyboardEvent* nativeKeyEvent =
-          static_cast<WidgetKeyboardEvent*>(nativeEvent);
+          aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
         if (nativeKeyEvent) {
           nsAutoTArray<uint32_t, 10> keys;
           nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, keys);
           hasAccessKeyCandidates = !keys.IsEmpty();
         }
       }
 
       // Cancel the access key flag unless we are pressing the access key.
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -402,17 +402,17 @@ nsMenuFrame::HandleEvent(nsPresContext* 
 
   nsWeakFrame weakFrame(this);
   if (*aEventStatus == nsEventStatus_eIgnore)
     *aEventStatus = nsEventStatus_eConsumeDoDefault;
 
   bool onmenu = IsOnMenu();
 
   if (aEvent->message == NS_KEY_PRESS && !IsDisabled()) {
-    WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
+    WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
     uint32_t keyCode = keyEvent->keyCode;
 #ifdef XP_MACOSX
     // On mac, open menulist on either up/down arrow or space (w/o Cmd pressed)
     if (!IsOpen() && ((keyEvent->charCode == NS_VK_SPACE && !keyEvent->IsMeta()) ||
         (keyCode == NS_VK_UP || keyCode == NS_VK_DOWN))) {
       *aEventStatus = nsEventStatus_eConsumeNoDefault;
       OpenMenu(false);
     }
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1597,20 +1597,22 @@ NS_IMETHODIMP nsChildView::DispatchEvent
 #ifdef DEBUG
   debug_DumpEvent(stdout, event->widget, event, nsAutoCString("something"), 0);
 #endif
 
   NS_ASSERTION(!(mTextInputHandler && mTextInputHandler->IsIMEComposing() &&
                  event->HasKeyEventMessage()),
     "Any key events should not be fired during IME composing");
 
-  if (event->mFlags.mIsSynthesizedForTests && event->HasKeyEventMessage()) {
-    WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(event);
-    nsresult rv = mTextInputHandler->AttachNativeKeyEvent(*keyEvent);
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (event->mFlags.mIsSynthesizedForTests) {
+    WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
+    if (keyEvent) {
+      nsresult rv = mTextInputHandler->AttachNativeKeyEvent(*keyEvent);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
   }
 
   aStatus = nsEventStatus_eIgnore;
 
   nsIWidgetListener* listener = mWidgetListener;
 
   // If the listener is NULL, check if the parent is a popup. If it is, then
   // this child is the popup content view attached to a popup. Get the
--- a/widget/windows/winrt/MetroWidget.cpp
+++ b/widget/windows/winrt/MetroWidget.cpp
@@ -628,17 +628,17 @@ MetroWidget::DeliverNextScrollEvent()
   delete msg;
 }
 
 // defined in nsWiondowBase, called from shared module KeyboardLayout.
 bool
 MetroWidget::DispatchKeyboardEvent(WidgetGUIEvent* aEvent)
 {
   MOZ_ASSERT(aEvent);
-  WidgetKeyboardEvent* oldKeyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
+  WidgetKeyboardEvent* oldKeyEvent = aEvent->AsKeyboardEvent();
   WidgetKeyboardEvent* keyEvent =
     new WidgetKeyboardEvent(oldKeyEvent->mFlags.mIsTrusted,
                             oldKeyEvent->message, oldKeyEvent->widget);
   // XXX note this leaves pluginEvent null, which is fine for now.
   keyEvent->AssignKeyEventData(*oldKeyEvent, true);
   mKeyEventQueue.Push(keyEvent);
   nsCOMPtr<nsIRunnable> runnable =
     NS_NewRunnableMethod(this, &MetroWidget::DeliverNextKeyboardEvent);