Bug 920425 part.28 Use mozilla::WidgetEvent::AsMouseEvent() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 22 Oct 2013 17:55:20 +0900
changeset 151601 a03c584f9874be67cf1d238518aa64f6411ef087
parent 151600 041018f175349cceac71204a20c56b614666f57c
child 151602 cd05abee0fcaec29f693f274982778945f09ffa8
push id35241
push usermasayuki@d-toybox.com
push dateTue, 22 Oct 2013 08:55:32 +0000
treeherdermozilla-inbound@0dc6eccf8c77 [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.28 Use mozilla::WidgetEvent::AsMouseEvent() r=smaug
content/base/src/Element.cpp
content/base/src/FragmentOrElement.cpp
content/events/src/nsDOMDragEvent.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMMouseEvent.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/html/content/src/HTMLButtonElement.cpp
content/html/content/src/HTMLImageElement.cpp
content/html/content/src/HTMLInputElement.cpp
content/html/content/src/HTMLLabelElement.cpp
content/html/content/src/HTMLTextAreaElement.cpp
dom/base/nsGlobalWindow.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/layers/composite/APZCTreeManager.cpp
layout/base/PositionedEventTargeting.cpp
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/forms/nsImageControlFrame.cpp
layout/forms/nsListControlFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsImageFrame.cpp
layout/xul/base/src/nsMenuFrame.cpp
layout/xul/base/src/nsResizerFrame.cpp
layout/xul/base/src/nsScrollbarButtonFrame.cpp
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSplitterFrame.cpp
layout/xul/base/src/nsTitleBarFrame.cpp
view/src/nsViewManager.cpp
widget/gtk/nsWindow.cpp
widget/qt/nsWindow.cpp
widget/windows/nsWindow.cpp
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -1446,20 +1446,21 @@ Element::DispatchClickEvent(nsPresContex
   NS_PRECONDITION(aStatus, "Null out param?");
 
   WidgetMouseEvent event(aSourceEvent->mFlags.mIsTrusted, NS_MOUSE_CLICK,
                          aSourceEvent->widget, WidgetMouseEvent::eReal);
   event.refPoint = aSourceEvent->refPoint;
   uint32_t clickCount = 1;
   float pressure = 0;
   uint16_t inputSource = 0;
-  if (aSourceEvent->eventStructType == NS_MOUSE_EVENT) {
-    clickCount = static_cast<WidgetMouseEvent*>(aSourceEvent)->clickCount;
-    pressure = static_cast<WidgetMouseEvent*>(aSourceEvent)->pressure;
-    inputSource = static_cast<WidgetMouseEvent*>(aSourceEvent)->inputSource;
+  WidgetMouseEvent* sourceMouseEvent = aSourceEvent->AsMouseEvent();
+  if (sourceMouseEvent) {
+    clickCount = sourceMouseEvent->clickCount;
+    pressure = sourceMouseEvent->pressure;
+    inputSource = sourceMouseEvent->inputSource;
   } else if (aSourceEvent->eventStructType == NS_KEY_EVENT) {
     inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
   }
   event.pressure = pressure;
   event.clickCount = clickCount;
   event.inputSource = inputSource;
   event.modifiers = aSourceEvent->modifiers;
   if (aExtraEventFlags) {
@@ -2220,18 +2221,17 @@ Element::PostHandleEventForLinks(nsEvent
     return NS_OK;
   }
 
   nsresult rv = NS_OK;
 
   switch (aVisitor.mEvent->message) {
   case NS_MOUSE_BUTTON_DOWN:
     {
-      if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-          static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
+      if (aVisitor.mEvent->AsMouseEvent()->button ==
             WidgetMouseEvent::eLeftButton) {
         // don't make the link grab the focus if there is no link handler
         nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
         nsIDocument *document = GetCurrentDoc();
         if (handler && document) {
           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
           if (fm) {
             aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -689,18 +689,17 @@ nsIContent::PreHandleEvent(nsEventChainP
   if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
        aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
       // Check if we should stop event propagation when event has just been
       // dispatched or when we're about to propagate from
       // chrome access only subtree.
       ((this == aVisitor.mEvent->originalTarget &&
         !ChromeOnlyAccess()) || isAnonForEvents)) {
      nsCOMPtr<nsIContent> relatedTarget =
-       do_QueryInterface(
-         static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->relatedTarget);
+       do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->relatedTarget);
     if (relatedTarget &&
         relatedTarget->OwnerDoc() == OwnerDoc()) {
 
       // If current target is anonymous for events or we know that related
       // target is descendant of an element which is anonymous for events,
       // we may want to stop event propagation.
       // If this is the original target, aVisitor.mRelatedTargetIsInAnon
       // must be updated.
--- a/content/events/src/nsDOMDragEvent.cpp
+++ b/content/events/src/nsDOMDragEvent.cpp
@@ -19,18 +19,17 @@ nsDOMDragEvent::nsDOMDragEvent(mozilla::
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
-    static_cast<WidgetMouseEvent*>(mEvent)->inputSource =
-      nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+    mEvent->AsMouseEvent()->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDragEvent, nsDOMMouseEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMDragEvent, nsDOMMouseEvent)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMDragEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDragEvent)
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -538,17 +538,17 @@ nsDOMEvent::DuplicatePrivateData()
       WidgetKeyboardEvent* keyEvent =
         new WidgetKeyboardEvent(false, msg, nullptr);
       keyEvent->AssignKeyEventData(*oldKeyEvent, true);
       newEvent = keyEvent;
       break;
     }
     case NS_MOUSE_EVENT:
     {
-      WidgetMouseEvent* oldMouseEvent = static_cast<WidgetMouseEvent*>(mEvent);
+      WidgetMouseEvent* oldMouseEvent = mEvent->AsMouseEvent();
       WidgetMouseEvent* mouseEvent =
         new WidgetMouseEvent(false, msg, nullptr, oldMouseEvent->reason);
       mouseEvent->AssignMouseEventData(*oldMouseEvent, true);
       newEvent = mouseEvent;
       break;
     }
     case NS_DRAG_EVENT:
     {
@@ -920,18 +920,17 @@ nsDOMEvent::GetEventPopupControlState(Wi
           abuse = openControlled;
         }
         break;
       }
     }
     break;
   case NS_MOUSE_EVENT :
     if (aEvent->mFlags.mIsTrusted &&
-        static_cast<WidgetMouseEvent*>(aEvent)->button ==
-          WidgetMouseEvent::eLeftButton) {
+        aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
       switch(aEvent->message) {
       case NS_MOUSE_BUTTON_UP :
         if (::PopupAllowedForEvent("mouseup"))
           abuse = openControlled;
         break;
       case NS_MOUSE_BUTTON_DOWN :
         if (::PopupAllowedForEvent("mousedown"))
           abuse = openControlled;
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -16,38 +16,32 @@ nsDOMMouseEvent::nsDOMMouseEvent(mozilla
                                  WidgetMouseEventBase* aEvent)
   : nsDOMUIEvent(aOwner, aPresContext, aEvent ? aEvent :
                  new WidgetMouseEvent(false, 0, nullptr,
                                       WidgetMouseEvent::eReal))
 {
   // There's no way to make this class' ctor allocate an WidgetMouseScrollEvent.
   // It's not that important, though, since a scroll event is not a real
   // DOM event.
-  
+
+  WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
-    static_cast<WidgetMouseEvent*>(mEvent)->inputSource =
-      nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+    mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
   }
 
-  switch (mEvent->eventStructType)
-  {
-    case NS_MOUSE_EVENT:
-      NS_ASSERTION(static_cast<WidgetMouseEvent*>(mEvent)->reason
-                     != WidgetMouseEvent::eSynthesized,
-                   "Don't dispatch DOM events from synthesized mouse events");
-      mDetail = static_cast<WidgetMouseEvent*>(mEvent)->clickCount;
-      break;
-    default:
-      break;
+  if (mouseEvent) {
+    MOZ_ASSERT(mouseEvent->reason != WidgetMouseEvent::eSynthesized,
+               "Don't dispatch DOM events from synthesized mouse events");
+    mDetail = mouseEvent->clickCount;
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMMouseEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMouseEvent)
@@ -73,18 +67,18 @@ nsDOMMouseEvent::InitMouseEvent(const ns
       mouseEventBase->relatedTarget = aRelatedTarget;
       mouseEventBase->button = aButton;
       mouseEventBase->InitBasicModifiers(aCtrlKey, aAltKey, aShiftKey, aMetaKey);
       mClientPoint.x = aClientX;
       mClientPoint.y = aClientY;
       mouseEventBase->refPoint.x = aScreenX;
       mouseEventBase->refPoint.y = aScreenY;
 
-      if (mEvent->eventStructType == NS_MOUSE_EVENT) {
-        WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(mEvent);
+      WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
+      if (mouseEvent) {
         mouseEvent->clickCount = aDetail;
       }
       break;
     }
     default:
        break;
   }
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -131,18 +131,17 @@ RoundDown(double aDouble)
                          static_cast<int32_t>(ceil(aDouble));
 }
 
 static inline bool
 IsMouseEventReal(WidgetEvent* aEvent)
 {
   NS_ABORT_IF_FALSE(aEvent->IsMouseDerivedEvent(), "Not a mouse event");
   // Return true if not synthesized.
-  return static_cast<WidgetMouseEvent*>(aEvent)->reason ==
-           WidgetMouseEvent::eReal;
+  return aEvent->AsMouseEvent()->reason == WidgetMouseEvent::eReal;
 }
 
 #ifdef DEBUG_DOCSHELL_FOCUS
 static void
 PrintDocTree(nsIDocShellTreeItem* aParentItem, int aLevel)
 {
   for (int32_t i=0;i<aLevel;i++) printf("  ");
 
@@ -1038,114 +1037,111 @@ nsEventStateManager::PreHandleEvent(nsPr
     ++gMouseOrKeyboardEventCounter;
   }
 
   *aStatus = nsEventStatus_eIgnore;
 
   nsMouseWheelTransaction::OnEvent(aEvent);
 
   switch (aEvent->message) {
-  case NS_MOUSE_BUTTON_DOWN:
-    switch (static_cast<WidgetMouseEvent*>(aEvent)->button) {
+  case NS_MOUSE_BUTTON_DOWN: {
+    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+    switch (mouseEvent->button) {
     case WidgetMouseEvent::eLeftButton:
 #ifndef XP_OS2
-      BeginTrackingDragGesture(aPresContext,
-                               static_cast<WidgetMouseEvent*>(aEvent),
-                               aTargetFrame);
+      BeginTrackingDragGesture(aPresContext, mouseEvent, aTargetFrame);
 #endif
-      mLClickCount = static_cast<WidgetMouseEvent*>(aEvent)->clickCount;
-      SetClickCount(aPresContext, static_cast<WidgetMouseEvent*>(aEvent),
-                    aStatus);
+      mLClickCount = mouseEvent->clickCount;
+      SetClickCount(aPresContext, mouseEvent, aStatus);
       sNormalLMouseEventInProcess = true;
       break;
     case WidgetMouseEvent::eMiddleButton:
-      mMClickCount = static_cast<WidgetMouseEvent*>(aEvent)->clickCount;
-      SetClickCount(aPresContext, static_cast<WidgetMouseEvent*>(aEvent),
-                    aStatus);
+      mMClickCount = mouseEvent->clickCount;
+      SetClickCount(aPresContext, mouseEvent, aStatus);
       break;
     case WidgetMouseEvent::eRightButton:
 #ifdef XP_OS2
-      BeginTrackingDragGesture(aPresContext,
-                               static_cast<WidgetMouseEvent*>(aEvent),
-                               aTargetFrame);
+      BeginTrackingDragGesture(aPresContext, mouseEvent, aTargetFrame);
 #endif
-      mRClickCount = static_cast<WidgetMouseEvent*>(aEvent)->clickCount;
-      SetClickCount(aPresContext, static_cast<WidgetMouseEvent*>(aEvent),
-                    aStatus);
+      mRClickCount = mouseEvent->clickCount;
+      SetClickCount(aPresContext, mouseEvent, aStatus);
       break;
     }
     break;
-  case NS_MOUSE_BUTTON_UP:
-    switch (static_cast<WidgetMouseEvent*>(aEvent)->button) {
+  }
+  case NS_MOUSE_BUTTON_UP: {
+    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+    switch (mouseEvent->button) {
       case WidgetMouseEvent::eLeftButton:
         if (Prefs::ClickHoldContextMenu()) {
           KillClickHoldTimer();
         }
 #ifndef XP_OS2
         StopTrackingDragGesture();
 #endif
         sNormalLMouseEventInProcess = false;
         // then fall through...
       case WidgetMouseEvent::eRightButton:
 #ifdef XP_OS2
         StopTrackingDragGesture();
 #endif
         // then fall through...
       case WidgetMouseEvent::eMiddleButton:
-        SetClickCount(aPresContext, static_cast<WidgetMouseEvent*>(aEvent),
-                      aStatus);
+        SetClickCount(aPresContext, mouseEvent, aStatus);
         break;
     }
     break;
+  }
   case NS_MOUSE_EXIT:
     // If the event is not a top-level window exit, then it's not
     // really an exit --- we may have traversed widget boundaries but
     // we're still in our toplevel window.
     {
-      WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
+      WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
       if (mouseEvent->exit != WidgetMouseEvent::eTopLevel) {
         // Treat it as a synthetic move so we don't generate spurious
         // "exit" or "move" events.  Any necessary "out" or "over" events
         // will be generated by GenerateMouseEnterExit
         mouseEvent->message = NS_MOUSE_MOVE;
         mouseEvent->reason = WidgetMouseEvent::eSynthesized;
         // then fall through...
       } else {
-        GenerateMouseEnterExit(static_cast<WidgetGUIEvent*>(aEvent));
+        GenerateMouseEnterExit(mouseEvent);
         //This is a window level mouse exit event and should stop here
         aEvent->message = 0;
         break;
       }
     }
-  case NS_MOUSE_MOVE:
+  case NS_MOUSE_MOVE: {
     // on the Mac, GenerateDragGesture() may not return until the drag
     // has completed and so |aTargetFrame| may have been deleted (moving
     // a bookmark, for example).  If this is the case, however, we know
     // that ClearFrameRefs() has been called and it cleared out
     // |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
     // into UpdateCursor().
-    GenerateDragGesture(aPresContext, static_cast<WidgetMouseEvent*>(aEvent));
+    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+    GenerateDragGesture(aPresContext, mouseEvent);
     UpdateCursor(aPresContext, aEvent, mCurrentTarget, aStatus);
-    GenerateMouseEnterExit(static_cast<WidgetGUIEvent*>(aEvent));
+    GenerateMouseEnterExit(mouseEvent);
     // Flush pending layout changes, so that later mouse move events
     // will go to the right nodes.
     FlushPendingEvents(aPresContext);
     break;
+  }
   case NS_DRAGDROP_GESTURE:
     if (Prefs::ClickHoldContextMenu()) {
       // an external drag gesture event came in, not generated internally
       // by Gecko. Make sure we get rid of the click-hold timer.
       KillClickHoldTimer();
     }
     break;
   case NS_DRAGDROP_OVER:
     // 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));
+    GenerateDragDropEnterExit(aPresContext, aEvent->AsDragEvent());
     break;
 
   case NS_KEY_PRESS:
     {
       WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
 
       int32_t modifierMask = 0;
       if (keyEvent->IsShift())
@@ -1592,18 +1588,17 @@ nsEventStateManager::DispatchCrossProces
   PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
   TabParent* remote = static_cast<TabParent*>(remoteBrowser);
   if (!remote) {
     return false;
   }
 
   switch (aEvent->eventStructType) {
   case NS_MOUSE_EVENT: {
-    WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
-    return remote->SendRealMouseEvent(*mouseEvent);
+    return remote->SendRealMouseEvent(*aEvent->AsMouseEvent());
   }
   case NS_KEY_EVENT: {
     return remote->SendRealKeyEvent(*aEvent->AsKeyboardEvent());
   }
   case NS_WHEEL_EVENT: {
     WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(aEvent);
     return remote->SendMouseWheelEvent(*wheelEvent);
   }
@@ -3175,18 +3170,18 @@ nsEventStateManager::PostHandleEvent(nsP
 
   //Keep the prescontext alive, we might need it after event dispatch
   nsRefPtr<nsPresContext> presContext = aPresContext;
   nsresult ret = NS_OK;
 
   switch (aEvent->message) {
   case NS_MOUSE_BUTTON_DOWN:
     {
-      if (static_cast<WidgetMouseEvent*>(aEvent)->button ==
-            WidgetMouseEvent::eLeftButton &&
+      WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+      if (mouseEvent->button == WidgetMouseEvent::eLeftButton &&
           !sNormalLMouseEventInProcess) {
         // We got a mouseup event while a mousedown event was being processed.
         // Make sure that the capturing content is cleared.
         nsIPresShell::SetCapturingContent(nullptr, 0);
         break;
       }
 
       nsCOMPtr<nsIContent> activeContent;
@@ -3305,19 +3300,19 @@ nsEventStateManager::PostHandleEvent(nsP
 #endif
                 fm->ClearFocus(mDocument->GetWindow());
               fm->SetFocusedWindow(mDocument->GetWindow());
             }
           }
         }
 
         // The rest is left button-specific.
-        if (static_cast<WidgetMouseEvent*>(aEvent)->button !=
-              WidgetMouseEvent::eLeftButton)
+        if (mouseEvent->button != WidgetMouseEvent::eLeftButton) {
           break;
+        }
 
         if (activeContent) {
           // The nearest enclosing element goes into the
           // :active state.  If we fail the QI to DOMElement,
           // then we know we're only a node, and that we need
           // to obtain our parent element and put it into :active
           // instead.
           nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(activeContent));
@@ -3364,18 +3359,17 @@ nsEventStateManager::PostHandleEvent(nsP
     {
       ClearGlobalActiveContent(this);
       if (IsMouseEventReal(aEvent)) {
         if (!mCurrentTarget) {
           GetEventTarget();
         }
         // Make sure to dispatch the click even if there is no frame for
         // the current target element. This is required for Web compatibility.
-        ret = CheckForAndDispatchClick(presContext,
-                                       static_cast<WidgetMouseEvent*>(aEvent),
+        ret = CheckForAndDispatchClick(presContext, aEvent->AsMouseEvent(),
                                        aStatus);
       }
 
       nsIPresShell *shell = presContext->GetPresShell();
       if (shell) {
         nsRefPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
         frameSelection->SetMouseDownState(false);
       }
@@ -3594,17 +3588,17 @@ nsEventStateManager::PostHandleEvent(nsP
         nsCOMPtr<nsIContent> targetContent;
         mCurrentTarget->GetContentForEvent(aEvent,
                                            getter_AddRefs(targetContent));
 
         nsCOMPtr<nsIWidget> widget = mCurrentTarget->GetNearestWidget();
         WidgetDragEvent event(aEvent->mFlags.mIsTrusted,
                               NS_DRAGDROP_DRAGDROP, widget);
 
-        WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
+        WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
         event.refPoint = mouseEvent->refPoint;
         if (mouseEvent->widget) {
           event.refPoint += LayoutDeviceIntPoint::FromUntyped(mouseEvent->widget->WidgetToScreenOffset());
         }
         event.refPoint -= LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset());
         event.modifiers = mouseEvent->modifiers;
         event.buttons = mouseEvent->buttons;
         event.inputSource = mouseEvent->inputSource;
@@ -3618,18 +3612,17 @@ nsEventStateManager::PostHandleEvent(nsP
       }
       sLastDragOverFrame = nullptr;
       ClearGlobalActiveContent(this);
       break;
     }
   case NS_DRAGDROP_EXIT:
      // make sure to fire the enter and exit_synth events after the
      // NS_DRAGDROP_EXIT event, otherwise we'll clean up too early
-    GenerateDragDropEnterExit(presContext,
-                              static_cast<WidgetGUIEvent*>(aEvent));
+    GenerateDragDropEnterExit(presContext, aEvent->AsDragEvent());
     break;
 
   case NS_KEY_UP:
     break;
 
   case NS_KEY_PRESS:
     if (nsEventStatus_eConsumeNoDefault != *aStatus) {
       WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
@@ -4021,17 +4014,17 @@ nsEventStateManager::IsHandlingUserInput
   }
 
   TimeDuration timeout = nsContentUtils::HandlingUserInputTimeout();
   return timeout <= TimeDuration(0) ||
          (TimeStamp::Now() - sHandlingInputStart) <= timeout;
 }
 
 nsIFrame*
-nsEventStateManager::DispatchMouseEvent(WidgetGUIEvent* aEvent,
+nsEventStateManager::DispatchMouseEvent(WidgetMouseEvent* aMouseEvent,
                                         uint32_t aMessage,
                                         nsIContent* aTargetContent,
                                         nsIContent* aRelatedContent)
 {
   // http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html#methods
   // "[When the mouse is locked on an element...e]vents that require the concept
   // of a mouse cursor must not be dispatched (for example: mouseover, mouseout).
   if (sIsPointerLocked &&
@@ -4047,24 +4040,24 @@ nsEventStateManager::DispatchMouseEvent(
       return nullptr;
     }
     nsCOMPtr<nsIContent> content = do_QueryInterface(pointerLockedElement);
     return mPresContext->GetPrimaryFrameFor(content);
   }
 
   PROFILER_LABEL("Input", "DispatchMouseEvent");
   nsEventStatus status = nsEventStatus_eIgnore;
-  WidgetMouseEvent event(aEvent->mFlags.mIsTrusted, aMessage, aEvent->widget,
-                         WidgetMouseEvent::eReal);
-  event.refPoint = aEvent->refPoint;
-  event.modifiers = static_cast<WidgetMouseEvent*>(aEvent)->modifiers;
-  event.buttons = static_cast<WidgetMouseEvent*>(aEvent)->buttons;
-  event.pluginEvent = static_cast<WidgetMouseEvent*>(aEvent)->pluginEvent;
+  WidgetMouseEvent event(aMouseEvent->mFlags.mIsTrusted, aMessage,
+                         aMouseEvent->widget, WidgetMouseEvent::eReal);
+  event.refPoint = aMouseEvent->refPoint;
+  event.modifiers = aMouseEvent->modifiers;
+  event.buttons = aMouseEvent->buttons;
+  event.pluginEvent = aMouseEvent->pluginEvent;
   event.relatedTarget = aRelatedContent;
-  event.inputSource = static_cast<WidgetMouseEvent*>(aEvent)->inputSource;
+  event.inputSource = aMouseEvent->inputSource;
 
   nsWeakFrame previousTarget = mCurrentTarget;
 
   mCurrentTargetContent = aTargetContent;
 
   nsIFrame* targetFrame = nullptr;
   if (aTargetContent) {
     nsESMEventCB callback(aTargetContent);
@@ -4085,18 +4078,18 @@ nsEventStateManager::DispatchMouseEvent(
   return targetFrame;
 }
 
 class MouseEnterLeaveDispatcher
 {
 public:
   MouseEnterLeaveDispatcher(nsEventStateManager* aESM,
                             nsIContent* aTarget, nsIContent* aRelatedTarget,
-                            WidgetGUIEvent* aEvent, uint32_t aType)
-  : mESM(aESM), mEvent(aEvent), mType(aType)
+                            WidgetMouseEvent* aMouseEvent, uint32_t aType)
+  : mESM(aESM), mMouseEvent(aMouseEvent), mType(aType)
   {
     nsPIDOMWindow* win =
       aTarget ? aTarget->OwnerDoc()->GetInnerWindow() : nullptr;
     if (win && win->HasMouseEnterLeaveEventListeners()) {
       mRelatedTarget = aRelatedTarget ?
         aRelatedTarget->FindFirstNonChromeOnlyAccessContent() : nullptr;
       nsINode* commonParent = nullptr;
       if (aTarget && aRelatedTarget) {
@@ -4114,34 +4107,36 @@ public:
       }
     }
   }
 
   ~MouseEnterLeaveDispatcher()
   {
     if (mType == NS_MOUSEENTER) {
       for (int32_t i = mTargets.Count() - 1; i >= 0; --i) {
-        mESM->DispatchMouseEvent(mEvent, mType, mTargets[i], mRelatedTarget);
+        mESM->DispatchMouseEvent(mMouseEvent, mType, mTargets[i],
+                                 mRelatedTarget);
       }
     } else {
       for (int32_t i = 0; i < mTargets.Count(); ++i) {
-        mESM->DispatchMouseEvent(mEvent, mType, mTargets[i], mRelatedTarget);
+        mESM->DispatchMouseEvent(mMouseEvent, mType, mTargets[i],
+                                 mRelatedTarget);
       }
     }
   }
 
   nsEventStateManager*   mESM;
   nsCOMArray<nsIContent> mTargets;
   nsCOMPtr<nsIContent>   mRelatedTarget;
-  WidgetGUIEvent*        mEvent;
+  WidgetMouseEvent*      mMouseEvent;
   uint32_t               mType;
 };
 
 void
-nsEventStateManager::NotifyMouseOut(WidgetGUIEvent* aEvent,
+nsEventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
                                     nsIContent* aMovingInto)
 {
   if (!mLastMouseOverElement)
     return;
   // Before firing mouseout, check for recursion
   if (mLastMouseOverElement == mFirstMouseOutEventElement)
     return;
 
@@ -4154,17 +4149,17 @@ nsEventStateManager::NotifyMouseOut(Widg
       subdocFrame->GetDocShell(getter_AddRefs(docshell));
       if (docshell) {
         nsRefPtr<nsPresContext> presContext;
         docshell->GetPresContext(getter_AddRefs(presContext));
 
         if (presContext) {
           nsEventStateManager* kidESM = presContext->EventStateManager();
           // Not moving into any element in this subdocument
-          kidESM->NotifyMouseOut(aEvent, nullptr);
+          kidESM->NotifyMouseOut(aMouseEvent, nullptr);
         }
       }
     }
   }
   // That could have caused DOM events which could wreak havoc. Reverify
   // things and be careful.
   if (!mLastMouseOverElement)
     return;
@@ -4178,31 +4173,31 @@ nsEventStateManager::NotifyMouseOut(Widg
   // two nearby elements both deep in the DOM tree that would be defeated by
   // switching the hover state to null here.
   if (!aMovingInto) {
     // Unset :hover
     SetContentState(nullptr, NS_EVENT_STATE_HOVER);
   }
 
   MouseEnterLeaveDispatcher leaveDispatcher(this, mLastMouseOverElement, aMovingInto,
-                                            aEvent, NS_MOUSELEAVE);
+                                            aMouseEvent, NS_MOUSELEAVE);
 
   // Fire mouseout
-  DispatchMouseEvent(aEvent, NS_MOUSE_EXIT_SYNTH,
+  DispatchMouseEvent(aMouseEvent, NS_MOUSE_EXIT_SYNTH,
                      mLastMouseOverElement, aMovingInto);
   
   mLastMouseOverFrame = nullptr;
   mLastMouseOverElement = nullptr;
   
   // Turn recursion protection back off
   mFirstMouseOutEventElement = nullptr;
 }
 
 void
-nsEventStateManager::NotifyMouseOver(WidgetGUIEvent* aEvent,
+nsEventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
                                      nsIContent* aContent)
 {
   NS_ASSERTION(aContent, "Mouse must be over something");
 
   if (mLastMouseOverElement == aContent)
     return;
 
   // Before firing mouseover, check for recursion
@@ -4215,42 +4210,42 @@ nsEventStateManager::NotifyMouseOver(Wid
   EnsureDocument(mPresContext);
   nsIDocument *parentDoc = mDocument->GetParentDocument();
   if (parentDoc) {
     nsIContent *docContent = parentDoc->FindContentForSubDocument(mDocument);
     if (docContent) {
       nsIPresShell *parentShell = parentDoc->GetShell();
       if (parentShell) {
         nsEventStateManager* parentESM = parentShell->GetPresContext()->EventStateManager();
-        parentESM->NotifyMouseOver(aEvent, docContent);
+        parentESM->NotifyMouseOver(aMouseEvent, docContent);
       }
     }
   }
   // Firing the DOM event in the parent document could cause all kinds
   // of havoc.  Reverify and take care.
   if (mLastMouseOverElement == aContent)
     return;
 
   // Remember mLastMouseOverElement as the related content for the
   // DispatchMouseEvent() call below, since NotifyMouseOut() resets it, bug 298477.
   nsCOMPtr<nsIContent> lastMouseOverElement = mLastMouseOverElement;
 
   MouseEnterLeaveDispatcher enterDispatcher(this, aContent, lastMouseOverElement,
-                                            aEvent, NS_MOUSEENTER);
+                                            aMouseEvent, NS_MOUSEENTER);
   
-  NotifyMouseOut(aEvent, aContent);
+  NotifyMouseOut(aMouseEvent, aContent);
 
   // Store the first mouseOver event we fire and don't refire mouseOver
   // to that element while the first mouseOver is still ongoing.
   mFirstMouseOverEventElement = aContent;
   
   SetContentState(aContent, NS_EVENT_STATE_HOVER);
   
   // Fire mouseover
-  mLastMouseOverFrame = DispatchMouseEvent(aEvent, NS_MOUSE_ENTER_SYNTH,
+  mLastMouseOverFrame = DispatchMouseEvent(aMouseEvent, NS_MOUSE_ENTER_SYNTH,
                                            aContent, lastMouseOverElement);
   mLastMouseOverElement = aContent;
   
   // Turn recursion protection back off
   mFirstMouseOverEventElement = nullptr;
 }
 
 // Returns the center point of the window's inner content area.
@@ -4292,103 +4287,104 @@ GetWindowInnerRectCenter(nsPIDOMWindow* 
   int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y);
 
   return LayoutDeviceIntPoint(
     aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2),
     aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2));
 }
 
 void
-nsEventStateManager::GenerateMouseEnterExit(WidgetGUIEvent* aEvent)
+nsEventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
 {
   EnsureDocument(mPresContext);
   if (!mDocument)
     return;
 
   // Hold onto old target content through the event and reset after.
   nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
 
-  switch(aEvent->message) {
+  switch(aMouseEvent->message) {
   case NS_MOUSE_MOVE:
     {
       // Mouse movement is reported on the MouseEvent.movement{X,Y} fields.
       // Movement is calculated in nsDOMUIEvent::GetMovementPoint() as:
       //   previous_mousemove_refPoint - current_mousemove_refPoint.
-      if (sIsPointerLocked && aEvent->widget) {
+      if (sIsPointerLocked && aMouseEvent->widget) {
         // The pointer is locked. If the pointer is not located at the center of
         // the window, dispatch a synthetic mousemove to return the pointer there.
         // Doing this between "real" pointer moves gives the impression that the
         // (locked) pointer can continue moving and won't stop at the screen
         // boundary. We cancel the synthetic event so that we don't end up
         // dispatching the centering move event to content.
         LayoutDeviceIntPoint center =
-          GetWindowInnerRectCenter(mDocument->GetWindow(), aEvent->widget,
+          GetWindowInnerRectCenter(mDocument->GetWindow(), aMouseEvent->widget,
                                    mPresContext);
-        aEvent->lastRefPoint = center;
-        if (aEvent->refPoint != center) {
+        aMouseEvent->lastRefPoint = center;
+        if (aMouseEvent->refPoint != center) {
           // Mouse move doesn't finish at the center of the window. Dispatch a
           // synthetic native mouse event to move the pointer back to the center
           // of the window, to faciliate more movement. But first, record that
           // we've dispatched a synthetic mouse movement, so we can cancel it
           // in the other branch here.
           sSynthCenteringPoint = center;
-          aEvent->widget->SynthesizeNativeMouseMove(
-            LayoutDeviceIntPoint::ToUntyped(center) + aEvent->widget->WidgetToScreenOffset());
-        } else if (aEvent->refPoint == sSynthCenteringPoint) {
+          aMouseEvent->widget->SynthesizeNativeMouseMove(
+            LayoutDeviceIntPoint::ToUntyped(center) +
+              aMouseEvent->widget->WidgetToScreenOffset());
+        } else if (aMouseEvent->refPoint == sSynthCenteringPoint) {
           // This is the "synthetic native" event we dispatched to re-center the
           // pointer. Cancel it so we don't expose the centering move to content.
-          aEvent->mFlags.mPropagationStopped = true;
+          aMouseEvent->mFlags.mPropagationStopped = true;
           // Clear sSynthCenteringPoint so we don't cancel other events
           // targeted at the center.
           sSynthCenteringPoint = kInvalidRefPoint;
         }
       } else if (sLastRefPoint == kInvalidRefPoint) {
         // We don't have a valid previous mousemove refPoint. This is either
         // the first move we've encountered, or the mouse has just re-entered
         // the application window. We should report (0,0) movement for this
         // case, so make the current and previous refPoints the same.
-        aEvent->lastRefPoint = aEvent->refPoint;
+        aMouseEvent->lastRefPoint = aMouseEvent->refPoint;
       } else {
-        aEvent->lastRefPoint = sLastRefPoint;
+        aMouseEvent->lastRefPoint = sLastRefPoint;
       }
 
       // Update the last known refPoint with the current refPoint.
-      sLastRefPoint = aEvent->refPoint;
+      sLastRefPoint = aMouseEvent->refPoint;
 
       // Get the target content target (mousemove target == mouseover target)
-      nsCOMPtr<nsIContent> targetElement = GetEventTargetContent(aEvent);
+      nsCOMPtr<nsIContent> targetElement = GetEventTargetContent(aMouseEvent);
       if (!targetElement) {
         // We're always over the document root, even if we're only
         // over dead space in a page (whose frame is not associated with
         // any content) or in print preview dead space
         targetElement = mDocument->GetRootElement();
       }
       if (targetElement) {
-        NotifyMouseOver(aEvent, targetElement);
+        NotifyMouseOver(aMouseEvent, targetElement);
       }
     }
     break;
   case NS_MOUSE_EXIT:
     {
       // This is actually the window mouse exit event. We're not moving
       // into any new element.
 
       if (mLastMouseOverFrame &&
-          nsContentUtils::GetTopLevelWidget(aEvent->widget) !=
+          nsContentUtils::GetTopLevelWidget(aMouseEvent->widget) !=
           nsContentUtils::GetTopLevelWidget(mLastMouseOverFrame->GetNearestWidget())) {
         // the MouseOut event widget doesn't have same top widget with
         // mLastMouseOverFrame, it's a spurious event for mLastMouseOverFrame
         break;
       }
 
       // Reset sLastRefPoint, so that we'll know not to report any
       // movement the next time we re-enter the window.
       sLastRefPoint = kInvalidRefPoint;
 
-      NotifyMouseOut(aEvent, nullptr);
+      NotifyMouseOut(aMouseEvent, nullptr);
     }
     break;
   }
 
   // reset mCurretTargetContent to what it was
   mCurrentTargetContent = targetBeforeEvent;
 }
 
@@ -4446,68 +4442,71 @@ nsEventStateManager::SetPointerLock(nsIW
     if (dragService) {
       dragService->Unsuppress();
     }
   }
 }
 
 void
 nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
-                                               WidgetGUIEvent* aEvent)
+                                               WidgetDragEvent* aDragEvent)
 {
   //Hold onto old target content through the event and reset after.
   nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
 
-  switch(aEvent->message) {
+  switch(aDragEvent->message) {
   case NS_DRAGDROP_OVER:
     {
       // when dragging from one frame to another, events are fired in the
       // order: dragexit, dragenter, dragleave
       if (sLastDragOverFrame != mCurrentTarget) {
         //We'll need the content, too, to check if it changed separately from the frames.
         nsCOMPtr<nsIContent> lastContent;
         nsCOMPtr<nsIContent> targetContent;
-        mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
+        mCurrentTarget->GetContentForEvent(aDragEvent,
+                                           getter_AddRefs(targetContent));
 
         if (sLastDragOverFrame) {
           //The frame has changed but the content may not have. Check before dispatching to content
-          sLastDragOverFrame->GetContentForEvent(aEvent, getter_AddRefs(lastContent));
+          sLastDragOverFrame->GetContentForEvent(aDragEvent,
+                                                 getter_AddRefs(lastContent));
 
           FireDragEnterOrExit(sLastDragOverFrame->PresContext(),
-                              aEvent, NS_DRAGDROP_EXIT_SYNTH,
+                              aDragEvent, NS_DRAGDROP_EXIT_SYNTH,
                               targetContent, lastContent, sLastDragOverFrame);
         }
 
-        FireDragEnterOrExit(aPresContext, aEvent, NS_DRAGDROP_ENTER,
+        FireDragEnterOrExit(aPresContext, aDragEvent, NS_DRAGDROP_ENTER,
                             lastContent, targetContent, mCurrentTarget);
 
         if (sLastDragOverFrame) {
           FireDragEnterOrExit(sLastDragOverFrame->PresContext(),
-                              aEvent, NS_DRAGDROP_LEAVE_SYNTH,
+                              aDragEvent, NS_DRAGDROP_LEAVE_SYNTH,
                               targetContent, lastContent, sLastDragOverFrame);
         }
 
         sLastDragOverFrame = mCurrentTarget;
       }
     }
     break;
 
   case NS_DRAGDROP_EXIT:
     {
       //This is actually the window mouse exit event.
       if (sLastDragOverFrame) {
         nsCOMPtr<nsIContent> lastContent;
-        sLastDragOverFrame->GetContentForEvent(aEvent, getter_AddRefs(lastContent));
+        sLastDragOverFrame->GetContentForEvent(aDragEvent,
+                                               getter_AddRefs(lastContent));
 
         nsRefPtr<nsPresContext> lastDragOverFramePresContext = sLastDragOverFrame->PresContext();
         FireDragEnterOrExit(lastDragOverFramePresContext,
-                            aEvent, NS_DRAGDROP_EXIT_SYNTH,
+                            aDragEvent, NS_DRAGDROP_EXIT_SYNTH,
                             nullptr, lastContent, sLastDragOverFrame);
         FireDragEnterOrExit(lastDragOverFramePresContext,
-                            aEvent, NS_DRAGDROP_LEAVE_SYNTH,
+                            aDragEvent, NS_DRAGDROP_LEAVE_SYNTH,
                             nullptr, lastContent, sLastDragOverFrame);
 
         sLastDragOverFrame = nullptr;
       }
     }
     break;
   }
 
@@ -4515,29 +4514,30 @@ nsEventStateManager::GenerateDragDropEnt
   mCurrentTargetContent = targetBeforeEvent;
 
   // Now flush all pending notifications, for better responsiveness.
   FlushPendingEvents(aPresContext);
 }
 
 void
 nsEventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
-                                         WidgetGUIEvent* aEvent,
+                                         WidgetDragEvent* aDragEvent,
                                          uint32_t aMsg,
                                          nsIContent* aRelatedTarget,
                                          nsIContent* aTargetContent,
                                          nsWeakFrame& aTargetFrame)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
-  WidgetDragEvent event(aEvent->mFlags.mIsTrusted, aMsg, aEvent->widget);
-  event.refPoint = aEvent->refPoint;
-  event.modifiers = static_cast<WidgetMouseEvent*>(aEvent)->modifiers;
-  event.buttons = static_cast<WidgetMouseEvent*>(aEvent)->buttons;
+  WidgetDragEvent event(aDragEvent->mFlags.mIsTrusted, aMsg,
+                        aDragEvent->widget);
+  event.refPoint = aDragEvent->refPoint;
+  event.modifiers = aDragEvent->modifiers;
+  event.buttons = aDragEvent->buttons;
   event.relatedTarget = aRelatedTarget;
-  event.inputSource = static_cast<WidgetMouseEvent*>(aEvent)->inputSource;
+  event.inputSource = aDragEvent->inputSource;
 
   mCurrentTargetContent = aTargetContent;
 
   if (aTargetContent != aRelatedTarget) {
     //XXX This event should still go somewhere!!
     if (aTargetContent)
       nsEventDispatcher::Dispatch(aTargetContent, aPresContext, &event,
                                   nullptr, &status);
@@ -5088,18 +5088,17 @@ nsEventStateManager::ContentRemoved(nsID
     mLastMouseOverElement = nullptr;
   }
 }
 
 bool
 nsEventStateManager::EventStatusOK(WidgetGUIEvent* aEvent)
 {
   return !(aEvent->message == NS_MOUSE_BUTTON_DOWN &&
-           static_cast<WidgetMouseEvent*>(aEvent)->button ==
-             WidgetMouseEvent::eLeftButton &&
+           aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
            !sNormalLMouseEventInProcess);
 }
 
 //-------------------------------------------
 // Access Key Registration
 //-------------------------------------------
 void
 nsEventStateManager::RegisterAccessKey(nsIContent* aContent, uint32_t aKey)
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -251,52 +251,54 @@ protected:
                     mozilla::WidgetEvent* aEvent,
                     nsIFrame* aTargetFrame,
                     nsEventStatus* aStatus);
   /**
    * Turn a GUI mouse event into a mouse event targeted at the specified
    * content.  This returns the primary frame for the content (or null
    * if it goes away during the event).
    */
-  nsIFrame* DispatchMouseEvent(mozilla::WidgetGUIEvent* aEvent,
+  nsIFrame* DispatchMouseEvent(mozilla::WidgetMouseEvent* aMouseEvent,
                                uint32_t aMessage,
                                nsIContent* aTargetContent,
                                nsIContent* aRelatedContent);
   /**
    * Synthesize DOM and frame mouseover and mouseout events from this
    * MOUSE_MOVE or MOUSE_EXIT event.
    */
-  void GenerateMouseEnterExit(mozilla::WidgetGUIEvent* aEvent);
+  void GenerateMouseEnterExit(mozilla::WidgetMouseEvent* aMouseEvent);
   /**
    * Tell this ESM and ESMs in parent documents that the mouse is
    * over some content in this document.
    */
-  void NotifyMouseOver(mozilla::WidgetGUIEvent* aEvent, nsIContent* aContent);
+  void NotifyMouseOver(mozilla::WidgetMouseEvent* aMouseEvent,
+                       nsIContent* aContent);
   /**
    * Tell this ESM and ESMs in affected child documents that the mouse
    * has exited this document's currently hovered content.
-   * @param aEvent the event that triggered the mouseout
+   * @param aMouseEvent the event that triggered the mouseout
    * @param aMovingInto the content node we've moved into.  This is used to set
    *        the relatedTarget for mouseout events.  Also, if it's non-null
    *        NotifyMouseOut will NOT change the current hover content to null;
    *        in that case the caller is responsible for updating hover state.
    */
-  void NotifyMouseOut(mozilla::WidgetGUIEvent* aEvent, nsIContent* aMovingInto);
+  void NotifyMouseOut(mozilla::WidgetMouseEvent* aMouseEvent,
+                      nsIContent* aMovingInto);
   void GenerateDragDropEnterExit(nsPresContext* aPresContext,
-                                 mozilla::WidgetGUIEvent* aEvent);
+                                 mozilla::WidgetDragEvent* aDragEvent);
   /**
    * Fire the dragenter and dragexit/dragleave events when the mouse moves to a
    * new target.
    *
    * @param aRelatedTarget relatedTarget to set for the event
    * @param aTargetContent target to set for the event
    * @param aTargetFrame target frame for the event
    */
   void FireDragEnterOrExit(nsPresContext* aPresContext,
-                           mozilla::WidgetGUIEvent* aEvent,
+                           mozilla::WidgetDragEvent* aDragEvent,
                            uint32_t aMsg,
                            nsIContent* aRelatedTarget,
                            nsIContent* aTargetContent,
                            nsWeakFrame& aTargetFrame);
   /**
    * Update the initial drag session data transfer with any changes that occur
    * on cloned data transfer objects used for events.
    */
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -276,56 +276,49 @@ HTMLButtonElement::PostHandleEvent(nsEve
                                         &status);
             aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
           }
         }
         break;// NS_KEY_PRESS
 
       case NS_MOUSE_BUTTON_DOWN:
         {
-          if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
-            if (static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                  WidgetMouseEvent::eLeftButton) {
-              if (aVisitor.mEvent->mFlags.mIsTrusted) {
-                nsEventStateManager* esm =
-                  aVisitor.mPresContext->EventStateManager();
-                nsEventStateManager::SetActiveManager(
-                  static_cast<nsEventStateManager*>(esm), this);
-              }
-              nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-              if (fm)
-                fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
-                                   nsIFocusManager::FLAG_NOSCROLL);
-              aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
-            } else if (
-              static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                WidgetMouseEvent::eMiddleButton ||
-              static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                WidgetMouseEvent::eRightButton) {
-              // cancel all of these events for buttons
-              //XXXsmaug What to do with these events? Why these should be cancelled?
-              if (aVisitor.mDOMEvent) {
-                aVisitor.mDOMEvent->StopPropagation();
-              }
+          WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+          if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
+            if (mouseEvent->mFlags.mIsTrusted) {
+              nsEventStateManager* esm =
+                aVisitor.mPresContext->EventStateManager();
+              nsEventStateManager::SetActiveManager(
+                static_cast<nsEventStateManager*>(esm), this);
+            }
+            nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+            if (fm)
+              fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
+                                 nsIFocusManager::FLAG_NOSCROLL);
+            mouseEvent->mFlags.mMultipleActionsPrevented = true;
+          } else if (mouseEvent->button == WidgetMouseEvent::eMiddleButton ||
+                     mouseEvent->button == WidgetMouseEvent::eRightButton) {
+            // cancel all of these events for buttons
+            //XXXsmaug What to do with these events? Why these should be cancelled?
+            if (aVisitor.mDOMEvent) {
+              aVisitor.mDOMEvent->StopPropagation();
             }
           }
         }
         break;
 
       // cancel all of these events for buttons
       //XXXsmaug What to do with these events? Why these should be cancelled?
       case NS_MOUSE_BUTTON_UP:
       case NS_MOUSE_DOUBLECLICK:
         {
-          if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-              aVisitor.mDOMEvent &&
-              (static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                 WidgetMouseEvent::eMiddleButton ||
-               static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                 WidgetMouseEvent::eRightButton)) {
+          WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+          if (aVisitor.mDOMEvent &&
+              (mouseEvent->button == WidgetMouseEvent::eMiddleButton ||
+               mouseEvent->button == WidgetMouseEvent::eRightButton)) {
             aVisitor.mDOMEvent->StopPropagation();
           }
         }
         break;
 
       case NS_MOUSE_ENTER_SYNTH:
         {
           aVisitor.mPresContext->EventStateManager()->
--- a/content/html/content/src/HTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -368,20 +368,17 @@ HTMLImageElement::AfterSetAttr(int32_t a
 
 nsresult
 HTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // If we are a map and get a mouse click, don't let it be handled by
   // the Generic Element as this could cause a click event to fire
   // twice, once by the image frame for the map and once by the Anchor
   // element. (bug 39723)
-  if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-      aVisitor.mEvent->message == NS_MOUSE_CLICK &&
-      static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-        WidgetMouseEvent::eLeftButton) {
+  if (aVisitor.mEvent->IsLeftClickEvent()) {
     bool isMap = false;
     GetIsMap(&isMap);
     if (isMap) {
       aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3167,18 +3167,17 @@ HTMLInputElement::PreHandleEvent(nsEvent
   // If mNoContentDispatch is true we will not allow content to handle
   // this event.  But to allow middle mouse button paste to work we must allow
   // middle clicks to go to text fields anyway.
   if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
     aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
   }
   if (IsSingleLineTextControl(false) &&
       aVisitor.mEvent->message == NS_MOUSE_CLICK &&
-      aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-      static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
+      aVisitor.mEvent->AsMouseEvent()->button ==
         WidgetMouseEvent::eMiddleButton) {
     aVisitor.mEvent->mFlags.mNoContentDispatch = false;
   }
 
   // We must cache type because mType may change during JS event (bug 2369)
   aVisitor.mItemFlags |= mType;
 
   // Fire onchange (if necessary), before we do the blur, bug 357684.
@@ -3669,21 +3668,19 @@ HTMLInputElement::PostHandleEvent(nsEven
         } break; // NS_KEY_PRESS || NS_KEY_UP
 
         case NS_MOUSE_BUTTON_DOWN:
         case NS_MOUSE_BUTTON_UP:
         case NS_MOUSE_DOUBLECLICK:
         {
           // cancel all of these events for buttons
           //XXXsmaug Why?
-          if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-              (static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                 WidgetMouseEvent::eMiddleButton ||
-               static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
-                 WidgetMouseEvent::eRightButton)) {
+          WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
+          if (mouseEvent->button == WidgetMouseEvent::eMiddleButton ||
+              mouseEvent->button == WidgetMouseEvent::eRightButton) {
             if (mType == NS_FORM_INPUT_BUTTON ||
                 mType == NS_FORM_INPUT_RESET ||
                 mType == NS_FORM_INPUT_SUBMIT) {
               if (aVisitor.mDOMEvent) {
                 aVisitor.mDOMEvent->StopPropagation();
               } else {
                 rv = NS_ERROR_FAILURE;
               }
@@ -3792,19 +3789,18 @@ HTMLInputElement::PostHandleEventForRang
       WidgetInputEvent* inputEvent = aVisitor.mEvent->AsInputEvent();
       if (inputEvent->IsShift() || inputEvent->IsControl() ||
           inputEvent->IsAlt() || inputEvent->IsMeta() ||
           inputEvent->IsAltGraph() || inputEvent->IsFn() ||
           inputEvent->IsOS()) {
         break; // ignore
       }
       if (aVisitor.mEvent->message == NS_MOUSE_BUTTON_DOWN) {
-        WidgetMouseEvent* mouseEvent =
-          static_cast<WidgetMouseEvent*>(aVisitor.mEvent);
-        if (mouseEvent->buttons == WidgetMouseEvent::eLeftButtonFlag) {
+        if (aVisitor.mEvent->AsMouseEvent()->buttons ==
+              WidgetMouseEvent::eLeftButtonFlag) {
           StartRangeThumbDrag(inputEvent);
         } else if (mIsDraggingRange) {
           CancelRangeThumbDrag();
         }
       } else {
         if (aVisitor.mEvent->AsTouchEvent()->touches.Length() == 1) {
           StartRangeThumbDrag(inputEvent);
         } else if (mIsDraggingRange) {
--- a/content/html/content/src/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -126,59 +126,56 @@ HTMLLabelElement::PostHandleEvent(nsEven
 
   // Strong ref because event dispatch is going to happen.
   nsRefPtr<Element> content = GetLabeledElement();
 
   if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
     mHandlingEvent = true;
     switch (aVisitor.mEvent->message) {
       case NS_MOUSE_BUTTON_DOWN:
-        NS_ASSERTION(aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT,
-                     "wrong event struct for event");
-        if (static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
+        if (aVisitor.mEvent->AsMouseEvent()->button ==
               WidgetMouseEvent::eLeftButton) {
           // We reset the mouse-down point on every event because there is
           // no guarantee we will reach the NS_MOUSE_CLICK code below.
           LayoutDeviceIntPoint* curPoint =
             new LayoutDeviceIntPoint(aVisitor.mEvent->refPoint);
           SetProperty(nsGkAtoms::labelMouseDownPtProperty,
                       static_cast<void*>(curPoint),
                       DestroyMouseDownPoint);
         }
         break;
 
       case NS_MOUSE_CLICK:
         if (aVisitor.mEvent->IsLeftClickEvent()) {
-          const WidgetMouseEvent* event =
-            static_cast<const WidgetMouseEvent*>(aVisitor.mEvent);
+          WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
           LayoutDeviceIntPoint* mouseDownPoint =
             static_cast<LayoutDeviceIntPoint*>(
               GetProperty(nsGkAtoms::labelMouseDownPtProperty));
 
           bool dragSelect = false;
           if (mouseDownPoint) {
             LayoutDeviceIntPoint dragDistance = *mouseDownPoint;
             DeleteProperty(nsGkAtoms::labelMouseDownPtProperty);
 
-            dragDistance -= aVisitor.mEvent->refPoint;
+            dragDistance -= mouseEvent->refPoint;
             const int CLICK_DISTANCE = 2;
             dragSelect = dragDistance.x > CLICK_DISTANCE ||
                          dragDistance.x < -CLICK_DISTANCE ||
                          dragDistance.y > CLICK_DISTANCE ||
                          dragDistance.y < -CLICK_DISTANCE;
           }
           // Don't click the for-content if we did drag-select text or if we
           // have a kbd modifier (which adjusts a selection).
-          if (dragSelect || event->IsShift() || event->IsControl() ||
-              event->IsAlt() || event->IsMeta()) {
+          if (dragSelect || mouseEvent->IsShift() || mouseEvent->IsControl() ||
+              mouseEvent->IsAlt() || mouseEvent->IsMeta()) {
             break;
           }
           // Only set focus on the first click of multiple clicks to prevent
           // to prevent immediate de-focus.
-          if (event->clickCount <= 1) {
+          if (mouseEvent->clickCount <= 1) {
             nsIFocusManager* fm = nsFocusManager::GetFocusManager();
             if (fm) {
               // Use FLAG_BYMOVEFOCUS here so that the label is scrolled to.
               // Also, within HTMLInputElement::PostHandleEvent, inputs will
               // be selected only when focused via a key or when the navigation
               // flag is used and we want to select the text on label clicks as
               // well.
               nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
@@ -191,22 +188,21 @@ HTMLLabelElement::PostHandleEvent(nsEven
           //    would do nothing.  If we wanted to do something
           //    sensible, we might send more events through like
           //    this.)  See bug 7554, bug 49897, and bug 96813.
           nsEventStatus status = aVisitor.mEventStatus;
           // Ok to use aVisitor.mEvent as parameter because DispatchClickEvent
           // will actually create a new event.
           EventFlags eventFlags;
           eventFlags.mMultipleActionsPrevented = true;
-          DispatchClickEvent(aVisitor.mPresContext,
-                             aVisitor.mEvent->AsInputEvent(),
+          DispatchClickEvent(aVisitor.mPresContext, mouseEvent,
                              content, false, &eventFlags, &status);
           // Do we care about the status this returned?  I don't think we do...
           // Don't run another <label> off of this click
-          aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
+          mouseEvent->mFlags.mMultipleActionsPrevented = true;
         }
         break;
     }
     mHandlingEvent = false;
   }
   return NS_OK;
 }
 
--- a/content/html/content/src/HTMLTextAreaElement.cpp
+++ b/content/html/content/src/HTMLTextAreaElement.cpp
@@ -472,18 +472,17 @@ HTMLTextAreaElement::PreHandleEvent(nsEv
 
   // If noContentDispatch is true we will not allow content to handle
   // this event.  But to allow middle mouse button paste to work we must allow 
   // middle clicks to go to text fields anyway.
   if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
     aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
   }
   if (aVisitor.mEvent->message == NS_MOUSE_CLICK &&
-      aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
-      static_cast<WidgetMouseEvent*>(aVisitor.mEvent)->button ==
+      aVisitor.mEvent->AsMouseEvent()->button ==
         WidgetMouseEvent::eMiddleButton) {
     aVisitor.mEvent->mFlags.mNoContentDispatch = false;
   }
 
   // Fire onchange (if necessary), before we do the blur, bug 370521.
   if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
     FireChangeEventIfNeeded();
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11791,22 +11791,20 @@ nsGlobalChromeWindow::BeginWindowMove(ns
   }
 #endif
 
   if (!widget) {
     return NS_OK;
   }
 
   NS_ENSURE_TRUE(aMouseDownEvent, NS_ERROR_FAILURE);
-  WidgetEvent* internalEvent = aMouseDownEvent->GetInternalNSEvent();
-  NS_ENSURE_TRUE(internalEvent &&
-                 internalEvent->eventStructType == NS_MOUSE_EVENT,
+  WidgetMouseEvent* mouseEvent =
+    aMouseDownEvent->GetInternalNSEvent()->AsMouseEvent();
+  NS_ENSURE_TRUE(mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT,
                  NS_ERROR_FAILURE);
-  WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(internalEvent);
-
   return widget->BeginMoveDrag(mouseEvent);
 }
 
 //Note: This call will lock the cursor, it will not change as it moves.
 //To unlock, the cursor must be set back to CURSOR_AUTO.
 NS_IMETHODIMP
 nsGlobalChromeWindow::SetCursor(const nsAString& aCursor)
 {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1859,20 +1859,21 @@ nsPluginInstanceOwner::ProcessMouseDown(
     
     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     if (fm) {
       nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
       fm->SetFocus(elem, 0);
     }
   }
 
-  WidgetEvent* event = aMouseEvent->GetInternalNSEvent();
-  if (event && event->eventStructType == NS_MOUSE_EVENT) {
-    mLastMouseDownButtonType = static_cast<WidgetMouseEvent*>(event)->button;
-    nsEventStatus rv = ProcessEvent(*static_cast<WidgetGUIEvent*>(event));
+  WidgetMouseEvent* mouseEvent =
+    aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
+  if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT) {
+    mLastMouseDownButtonType = mouseEvent->button;
+    nsEventStatus rv = ProcessEvent(*mouseEvent);
     if (nsEventStatus_eConsumeNoDefault == rv) {
       return aMouseEvent->PreventDefault(); // consume event
     }
   }
   
   return NS_OK;
 }
 
@@ -1921,19 +1922,19 @@ nsPluginInstanceOwner::HandleEvent(nsIDO
   }
   if (eventType.EqualsLiteral("mouseup")) {
     // Don't send a mouse-up event to the plugin if its button type doesn't
     // match that of the preceding mouse-down event (if any).  This kind of
     // mismatch can happen if the previous mouse-down event was sent to a DOM
     // element above the plugin, the mouse is still above the plugin, and the
     // mouse-down event caused the element to disappear.  See bug 627649 and
     // bug 909678.
-    WidgetMouseEvent *event =
-      static_cast<WidgetMouseEvent*>(aEvent->GetInternalNSEvent());
-    if (event && ((int) event->button != mLastMouseDownButtonType)) {
+    WidgetMouseEvent* mouseEvent = aEvent->GetInternalNSEvent()->AsMouseEvent();
+    if (mouseEvent &&
+        static_cast<int>(mouseEvent->button) != mLastMouseDownButtonType) {
       aEvent->PreventDefault();
       return NS_OK;
     }
     return DispatchMouseToPlugin(aEvent);
   }
   if (eventType.EqualsLiteral("mousemove") ||
       eventType.EqualsLiteral("click") ||
       eventType.EqualsLiteral("dblclick") ||
@@ -2033,18 +2034,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
         synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
         synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
         event = &synthCocoaEvent;
         break;
       case NS_MOUSE_BUTTON_UP:
         // If we're in a dragging operation that started over another frame,
         // convert it into a mouse-entered event (in the Cocoa Event Model).
         // See bug 525078.
-        if ((static_cast<const WidgetMouseEvent&>(anEvent).button ==
-               WidgetMouseEvent::eLeftButton) &&
+        if (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
             (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) {
           synthCocoaEvent.type = NPCocoaEventMouseEntered;
           synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
           synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
           event = &synthCocoaEvent;
         } else {
           synthCocoaEvent.type = NPCocoaEventMouseUp;
           synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
@@ -2069,39 +2069,37 @@ nsEventStatus nsPluginInstanceOwner::Pro
     mInstance->HandleEvent(event, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
   }
 
   if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
     pluginWidget->StartComplexTextInputForCurrentEvent();
   }
 
   if ((response == kNPEventHandled || response == kNPEventStartIME) &&
-      !(anEvent.eventStructType == NS_MOUSE_EVENT &&
-        anEvent.message == NS_MOUSE_BUTTON_DOWN &&
-        static_cast<const WidgetMouseEvent&>(anEvent).button ==
-          WidgetMouseEvent::eLeftButton &&
-        !mContentFocused))
+      !(anEvent.message == NS_MOUSE_BUTTON_DOWN &&
+        anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
+        !mContentFocused)) {
     rv = nsEventStatus_eConsumeNoDefault;
+  }
 
   pluginWidget->EndDrawPlugin();
 #endif
 
 #ifdef XP_WIN
   // this code supports windowless plugins
   NPEvent *pPluginEvent = (NPEvent*)anEvent.pluginEvent;
   // we can get synthetic events from the nsEventStateManager... these
   // have no pluginEvent
   NPEvent pluginEvent;
   if (anEvent.eventStructType == NS_MOUSE_EVENT) {
     if (!pPluginEvent) {
       // XXX Should extend this list to synthesize events for more event
       // types
       pluginEvent.event = 0;
-      const WidgetMouseEvent* mouseEvent =
-        static_cast<const WidgetMouseEvent*>(&anEvent);
+      const WidgetMouseEvent* mouseEvent = anEvent.AsMouseEvent();
       switch (anEvent.message) {
       case NS_MOUSE_MOVE:
         pluginEvent.event = WM_MOUSEMOVE;
         break;
       case NS_MOUSE_BUTTON_DOWN: {
         static const int downMsgs[] =
           { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
         static const int dblClickMsgs[] =
@@ -2210,18 +2208,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
 
         // Get reference point relative to plugin origin.
         const nsPresContext* presContext = mObjectFrame->PresContext();
         nsPoint appPoint =
           nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
           mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
         nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
                                presContext->AppUnitsToDevPixels(appPoint.y));
-        const WidgetMouseEvent& mouseEvent =
-          static_cast<const WidgetMouseEvent&>(anEvent);
+        const WidgetMouseEvent& mouseEvent = *anEvent.AsMouseEvent();
         // Get reference point relative to screen:
         LayoutDeviceIntPoint rootPoint(-1, -1);
         if (widget)
           rootPoint = anEvent.refPoint +
             LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset());
 #ifdef MOZ_WIDGET_GTK
         Window root = GDK_ROOT_WINDOW();
 #elif defined(MOZ_WIDGET_QT)
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -367,18 +367,17 @@ APZCTreeManager::ProcessMouseEvent(const
     return nsEventStatus_eIgnore;
   }
   gfx3DMatrix transformToApzc;
   gfx3DMatrix transformToScreen;
   GetInputTransforms(apzc, transformToApzc, transformToScreen);
   MultiTouchInput inputForApzc(aEvent);
   ApplyTransform(&(inputForApzc.mTouches[0].mScreenPoint), transformToApzc);
   gfx3DMatrix outTransform = transformToApzc * transformToScreen;
-  ApplyTransform(&(static_cast<WidgetMouseEvent*>(aOutEvent)->refPoint),
-                 outTransform);
+  ApplyTransform(&aOutEvent->refPoint, outTransform);
   return apzc->ReceiveInputEvent(inputForApzc);
 }
 
 nsEventStatus
 APZCTreeManager::ProcessEvent(const WidgetInputEvent& aEvent,
                               WidgetInputEvent* aOutEvent)
 {
   // Transform the refPoint
@@ -413,20 +412,19 @@ APZCTreeManager::ReceiveInputEvent(const
       }
       if (!mApzcForInputBlock) {
         return nsEventStatus_eIgnore;
       }
       return ProcessTouchEvent(touchEvent, aOutEvent->AsTouchEvent());
     }
     case NS_MOUSE_EVENT: {
       // For b2g emulation
-      const WidgetMouseEvent& mouseEvent =
-        static_cast<const WidgetMouseEvent&>(aEvent);
-      WidgetMouseEvent* outEvent = static_cast<WidgetMouseEvent*>(aOutEvent);
-      return ProcessMouseEvent(mouseEvent, outEvent);
+      const WidgetMouseEvent& mouseEvent = *aEvent.AsMouseEvent();
+      WidgetMouseEvent* outMouseEvent = aOutEvent->AsMouseEvent();
+      return ProcessMouseEvent(mouseEvent, outMouseEvent);
     }
     default: {
       return ProcessEvent(aEvent, aOutEvent);
     }
   }
 }
 
 nsEventStatus
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -342,19 +342,19 @@ FindFrameTargetedByInputEvent(const Widg
   if (!prefs || !prefs->mEnabled || (target && IsElementClickable(target, nsGkAtoms::body))) {
     return target;
   }
 
   // Do not modify targeting for actual mouse hardware; only for mouse
   // events generated by touch-screen hardware.
   if (aEvent->eventStructType == NS_MOUSE_EVENT &&
       prefs->mTouchOnly &&
-      static_cast<const WidgetMouseEvent*>(aEvent)->inputSource !=
-          nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
-      return target;
+      aEvent->AsMouseEvent()->inputSource !=
+        nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
+    return target;
   }
 
   nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame, prefs);
   nsAutoTArray<nsIFrame*,8> candidates;
   nsresult rv = nsLayoutUtils::GetFramesForArea(aRootFrame, targetRect, candidates, flags);
   if (NS_FAILED(rv)) {
     return target;
   }
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5883,18 +5883,17 @@ PresShell::RecordMouseLocation(WidgetGUI
     PresShell* rootPresShell = GetRootPresShell();
     if (rootPresShell) {
       rootPresShell->RecordMouseLocation(aEvent);
     }
     return;
   }
 
   if ((aEvent->message == NS_MOUSE_MOVE &&
-       static_cast<WidgetMouseEvent*>(aEvent)->reason ==
-         WidgetMouseEvent::eReal) ||
+       aEvent->AsMouseEvent()->reason == WidgetMouseEvent::eReal) ||
       aEvent->message == NS_MOUSE_ENTER ||
       aEvent->message == NS_MOUSE_BUTTON_DOWN ||
       aEvent->message == NS_MOUSE_BUTTON_UP) {
     nsIFrame* rootFrame = GetRootFrame();
     if (!rootFrame) {
       nsView* rootView = mViewManager->GetRootView();
       mMouseLocation = nsLayoutUtils::TranslateWidgetToView(mPresContext,
         aEvent->widget, LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint),
@@ -6180,19 +6179,19 @@ PresShell::HandleEvent(nsIFrame* aFrame,
     }
 
     // all touch events except for touchstart use a captured target
     if (aEvent->eventStructType == NS_TOUCH_EVENT &&
         aEvent->message != NS_TOUCH_START) {
       captureRetarget = true;
     }
 
+    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
     bool isWindowLevelMouseExit = (aEvent->message == NS_MOUSE_EXIT) &&
-      (static_cast<WidgetMouseEvent*>(aEvent)->exit ==
-         WidgetMouseEvent::eTopLevel);
+      (mouseEvent && mouseEvent->exit == WidgetMouseEvent::eTopLevel);
 
     // Get the frame at the event point. However, don't do this if we're
     // capturing and retargeting the event because the captured frame will
     // be used instead below. Also keep using the root frame if we're dealing
     // with a window-level mouse exit event since we want to start sending
     // mouse out events at the root EventStateManager.
     if (!captureRetarget && !isWindowLevelMouseExit) {
       nsPoint eventPoint;
@@ -6273,18 +6272,18 @@ PresShell::HandleEvent(nsIFrame* aFrame,
             if (oldTouch) {
               touch->SetTarget(oldTouch->mTarget);
             }
           }
         }
       } else {
         eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
       }
-      if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-          static_cast<WidgetMouseEvent*>(aEvent)->ignoreRootScrollFrame) {
+      if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT &&
+          mouseEvent->ignoreRootScrollFrame) {
         flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
       }
       nsIFrame* target =
         FindFrameTargetedByInputEvent(aEvent, frame, eventPoint, flags);
       if (target) {
         frame = target;
       }
     }
@@ -6309,18 +6308,17 @@ PresShell::HandleEvent(nsIFrame* aFrame,
 
     // Suppress mouse event if it's being targeted at an element inside
     // a document which needs events suppressed
     if (aEvent->eventStructType == NS_MOUSE_EVENT &&
         frame->PresContext()->Document()->EventHandlingSuppressed()) {
       if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
         mNoDelayedMouseEvents = true;
       } else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
-        nsDelayedEvent* event =
-          new nsDelayedMouseEvent(static_cast<WidgetMouseEvent*>(aEvent));
+        nsDelayedEvent* event = new nsDelayedMouseEvent(aEvent->AsMouseEvent());
         if (!mDelayedEvents.AppendElement(event)) {
           delete event;
         }
       }
 
       return NS_OK;
     }
 
@@ -6829,25 +6827,25 @@ PresShell::HandleEventInternal(WidgetEve
             aEvent->mFlags.mOnlyChromeDispatch = true;
           }
         }
         break;
       }
     }
 
     if (aEvent->message == NS_CONTEXTMENU) {
-      WidgetMouseEvent* me = static_cast<WidgetMouseEvent*>(aEvent);
-      if (!CanHandleContextMenuEvent(me, GetCurrentEventFrame())) {
+      WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+      if (!CanHandleContextMenuEvent(mouseEvent, GetCurrentEventFrame())) {
         return NS_OK;
       }
-      if (me->context == WidgetMouseEvent::eContextMenuKey &&
-          !AdjustContextMenuKeyEvent(me)) {
+      if (mouseEvent->context == WidgetMouseEvent::eContextMenuKey &&
+          !AdjustContextMenuKeyEvent(mouseEvent)) {
         return NS_OK;
       }
-      if (me->IsShift()) {
+      if (mouseEvent->IsShift()) {
         aEvent->mFlags.mOnlyChromeDispatch = true;
         aEvent->mFlags.mRetargetToNonNativeAnonymous = true;
       }
     }
 
     nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
                                                           aEvent, mDocument);
 
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -579,23 +579,24 @@ protected:
   };
 
   class nsDelayedMouseEvent : public nsDelayedInputEvent
   {
   public:
     nsDelayedMouseEvent(mozilla::WidgetMouseEvent* aEvent) :
       nsDelayedInputEvent()
     {
-      mEvent = new mozilla::WidgetMouseEvent(aEvent->mFlags.mIsTrusted,
-                                             aEvent->message,
-                                             aEvent->widget,
-                                             aEvent->reason,
-                                             aEvent->context);
-      static_cast<mozilla::WidgetMouseEvent*>(mEvent)->
-        AssignMouseEventData(*aEvent, false);
+      mozilla::WidgetMouseEvent* mouseEvent =
+        new mozilla::WidgetMouseEvent(aEvent->mFlags.mIsTrusted,
+                                      aEvent->message,
+                                      aEvent->widget,
+                                      aEvent->reason,
+                                      aEvent->context);
+      mouseEvent->AssignMouseEventData(*aEvent, false);
+      mEvent = mouseEvent;
     }
   };
 
   class nsDelayedKeyEvent : public nsDelayedInputEvent
   {
   public:
     nsDelayedKeyEvent(mozilla::WidgetKeyboardEvent* aEvent) :
       nsDelayedInputEvent()
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -164,20 +164,18 @@ nsImageControlFrame::HandleEvent(nsPresC
     return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
 
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) { // XXX cache disabled
     return NS_OK;
   }
 
   *aEventStatus = nsEventStatus_eIgnore;
 
-  if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-      aEvent->message == NS_MOUSE_BUTTON_UP &&
-      static_cast<WidgetMouseEvent*>(aEvent)->button ==
-        WidgetMouseEvent::eLeftButton) {
+  if (aEvent->message == NS_MOUSE_BUTTON_UP &&
+      aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
     // Store click point for HTMLInputElement::SubmitNamesValues
     // Do this on MouseUp because the specs don't say and that's what IE does
     nsIntPoint* lastClickPoint =
       static_cast<nsIntPoint*>
                  (mContent->GetProperty(nsGkAtoms::imageClickedPoint));
     if (lastClickPoint) {
       // normally lastClickedPoint is not null, as it's allocated in Init()
       nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -1603,17 +1603,17 @@ nsListControlFrame::MouseUp(nsIDOMEvent*
     // And then NOT get an "onclick" event when when you click down on the select
     // and then up outside of the select
     // the EventStateManager tracks the content of the mouse down and the mouse up
     // to make sure they are the same, and the onclick is sent in the PostHandleEvent
     // depeneding on whether the clickCount is non-zero.
     // So we cheat here by either setting or unsetting the clcikCount in the native event
     // so the right thing happens for the onclick event
     WidgetMouseEvent* mouseEvent =
-      static_cast<WidgetMouseEvent*>(aMouseEvent->GetInternalNSEvent());
+      aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
 
     int32_t selectedIndex;
     if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
       // If it's disabled, disallow the click and leave.
       bool isDisabled = false;
       IsOptionDisabled(selectedIndex, isDisabled);
       if (isDisabled) {
         aMouseEvent->PreventDefault();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2340,22 +2340,23 @@ nsFrame::FireDOMEvent(const nsAString& a
 
 NS_IMETHODIMP
 nsFrame::HandleEvent(nsPresContext* aPresContext, 
                      WidgetGUIEvent* aEvent,
                      nsEventStatus* aEventStatus)
 {
 
   if (aEvent->message == NS_MOUSE_MOVE) {
+    // XXX If the second argument of HandleDrag() is WidgetMouseEvent,
+    //     the implementation becomes simpler.
     return HandleDrag(aPresContext, aEvent, aEventStatus);
   }
 
   if ((aEvent->eventStructType == NS_MOUSE_EVENT &&
-      static_cast<WidgetMouseEvent*>(aEvent)->button ==
-        WidgetMouseEvent::eLeftButton) ||
+       aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) ||
       aEvent->eventStructType == NS_TOUCH_EVENT) {
     if (aEvent->message == NS_MOUSE_BUTTON_DOWN || aEvent->message == NS_TOUCH_START) {
       HandlePress(aPresContext, aEvent, aEventStatus);
     } else if (aEvent->message == NS_MOUSE_BUTTON_UP || aEvent->message == NS_TOUCH_END) {
       HandleRelease(aPresContext, aEvent, aEventStatus);
     }
   }
   return NS_OK;
@@ -2580,25 +2581,28 @@ nsFrame::HandlePress(nsPresContext* aPre
 
   // if we are in Navigator and the click is in a draggable node, we don't want
   // to start selection because we don't want to interfere with a potential
   // drag of said node and steal all its glory.
   int16_t isEditor = shell->GetSelectionFlags();
   //weaaak. only the editor can display frame selection not just text and images
   isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
 
-  if (!aEvent->AsInputEvent()->IsAlt()) {
+  WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+
+  if (!mouseEvent->IsAlt()) {
     for (nsIContent* content = mContent; content;
          content = content->GetParent()) {
       if (nsContentUtils::ContentIsDraggable(content) &&
           !content->IsEditable()) {
         // coordinate stuff is the fix for bug #55921
         if ((mRect - GetPosition()).Contains(
-               nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this)))
+              nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent, this))) {
           return NS_OK;
+        }
       }
     }
   }
 
   // check whether style allows selection
   // if not, don't tell selection the mouse event even occurred.  
   bool    selectable;
   uint8_t selectStyle;
@@ -2636,37 +2640,34 @@ nsFrame::HandlePress(nsPresContext* aPre
   if (useFrameSelection)
     frameselection = GetConstFrameSelection();
   else
     frameselection = shell->ConstFrameSelection();
 
   if (!frameselection || frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
     return NS_OK;//nothing to do we cannot affect selection from here
 
-  WidgetMouseEvent* me = static_cast<WidgetMouseEvent*>(aEvent);
-
 #ifdef XP_MACOSX
-  if (me->IsControl())
+  if (mouseEvent->IsControl())
     return NS_OK;//short circuit. hard coded for mac due to time restraints.
-  bool control = me->IsMeta();
+  bool control = mouseEvent->IsMeta();
 #else
-  bool control = me->IsControl();
+  bool control = mouseEvent->IsControl();
 #endif
 
   nsRefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
-  if (me->clickCount > 1)
-  {
+  if (mouseEvent->clickCount > 1) {
     // These methods aren't const but can't actually delete anything,
     // so no need for nsWeakFrame.
     fc->SetMouseDownState(true);
     fc->SetMouseDoubleDown(true);
-    return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
-  }
-
-  nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
+    return HandleMultiplePress(aPresContext, mouseEvent, aEventStatus, control);
+  }
+
+  nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent, this);
   ContentOffsets offsets = GetContentOffsetsFromPoint(pt, SKIP_HIDDEN);
 
   if (!offsets.content)
     return NS_ERROR_FAILURE;
 
   // On touchables devices, touch the screen is usually a pan action,
   // so let's reposition the caret if needed but do not select text
   // if the touch did not happen over an editable element.  Otherwise,
@@ -2677,21 +2678,24 @@ nsFrame::HandlePress(nsPresContext* aPre
                            offsets.EndOffset(), false, false,
                            offsets.associateWithNext);
   }
 
   // Let Ctrl/Cmd+mouse down do table selection instead of drag initiation
   nsCOMPtr<nsIContent>parentContent;
   int32_t  contentOffset;
   int32_t target;
-  rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
+  rv = GetDataForTableSelection(frameselection, shell, mouseEvent,
+                                getter_AddRefs(parentContent), &contentOffset,
+                                &target);
   if (NS_SUCCEEDED(rv) && parentContent)
   {
     fc->SetMouseDownState(true);
-    return fc->HandleTableSelection(parentContent, contentOffset, target, me);
+    return fc->HandleTableSelection(parentContent, contentOffset, target,
+                                    mouseEvent);
   }
 
   fc->SetDelayedCaretData(0);
 
   // Check if any part of this frame is selected, and if the
   // user clicked inside the selected region. If so, we delay
   // starting a new selection since the user may be trying to
   // drag the selected region to some other app.
@@ -2729,36 +2733,36 @@ nsFrame::HandlePress(nsPresContext* aPre
 
       SelectionDetails *nextDetail = curDetail->mNext;
       delete curDetail;
       curDetail = nextDetail;
     }
 
     if (inSelection) {
       fc->SetMouseDownState(false);
-      fc->SetDelayedCaretData(me);
+      fc->SetDelayedCaretData(mouseEvent);
       return NS_OK;
     }
   }
 
   fc->SetMouseDownState(true);
 
   // Do not touch any nsFrame members after this point without adding
   // weakFrame checks.
   rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
-                       offsets.EndOffset(), me->IsShift(), control,
+                       offsets.EndOffset(), mouseEvent->IsShift(), control,
                        offsets.associateWithNext);
 
   if (NS_FAILED(rv))
     return rv;
 
   if (offsets.offset != offsets.secondaryOffset)
     fc->MaintainSelection();
 
-  if (isEditor && !me->IsShift() &&
+  if (isEditor && !mouseEvent->IsShift() &&
       (offsets.EndOffset() - offsets.StartOffset()) == 1)
   {
     // A single node is selected and we aren't extending an existing
     // selection, which means the user clicked directly on an object (either
     // -moz-user-select: all or a non-text node without children).
     // Therefore, disable selection extension during mouse moves.
     // XXX This is a bit hacky; shouldn't editor be able to deal with this?
     fc->SetMouseDownState(false);
@@ -2833,36 +2837,39 @@ nsFrame::HandleMultiplePress(nsPresConte
     return NS_OK;
   }
 
   // Find out whether we're doing line or paragraph selection.
   // If browser.triple_click_selects_paragraph is true, triple-click selects paragraph.
   // Otherwise, triple-click selects line, and quadruple-click selects paragraph
   // (on platforms that support quadruple-click).
   nsSelectionAmount beginAmount, endAmount;
-  WidgetMouseEvent* me = static_cast<WidgetMouseEvent*>(aEvent);
-  if (!me) return NS_OK;
-
-  if (me->clickCount == 4) {
+  WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+  if (!mouseEvent) {
+    return NS_OK;
+  }
+
+  if (mouseEvent->clickCount == 4) {
     beginAmount = endAmount = eSelectParagraph;
-  } else if (me->clickCount == 3) {
+  } else if (mouseEvent->clickCount == 3) {
     if (Preferences::GetBool("browser.triple_click_selects_paragraph")) {
       beginAmount = endAmount = eSelectParagraph;
     } else {
       beginAmount = eSelectBeginLine;
       endAmount = eSelectEndLine;
     }
-  } else if (me->clickCount == 2) {
+  } else if (mouseEvent->clickCount == 2) {
     // We only want inline frames; PeekBackwardAndForward dislikes blocks
     beginAmount = endAmount = eSelectWord;
   } else {
     return NS_OK;
   }
 
-  nsPoint relPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
+  nsPoint relPoint =
+    nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent, this);
   return SelectByTypeAtPoint(aPresContext, relPoint, beginAmount, endAmount,
                              (aControlHeld ? SELECT_ACCUMULATE : 0));
 }
 
 nsresult
 nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
                                 nsSelectionAmount aAmountForward,
                                 int32_t aStartPos,
@@ -2963,27 +2970,28 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
     return NS_OK;
 
   frameselection->StopAutoScrollTimer();
 
   // Check if we are dragging in a table cell
   nsCOMPtr<nsIContent> parentContent;
   int32_t contentOffset;
   int32_t target;
-  WidgetMouseEvent* me = static_cast<WidgetMouseEvent*>(aEvent);
+  WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   nsresult result;
-  result = GetDataForTableSelection(frameselection, presShell, me,
+  result = GetDataForTableSelection(frameselection, presShell, mouseEvent,
                                     getter_AddRefs(parentContent),
                                     &contentOffset, &target);      
 
   nsWeakFrame weakThis = this;
   if (NS_SUCCEEDED(result) && parentContent) {
-    frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
+    frameselection->HandleTableSelection(parentContent, contentOffset, target,
+                                         mouseEvent);
   } else {
-    nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
+    nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent, this);
     frameselection->HandleDrag(this, pt);
   }
 
   // The frameselection object notifies selection listeners synchronously above
   // which might have killed us.
   if (!weakThis.IsAlive()) {
     return NS_OK;
   }
@@ -2992,18 +3000,18 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
   nsIScrollableFrame* scrollFrame =
     nsLayoutUtils::GetNearestScrollableFrame(this,
         nsLayoutUtils::SCROLLABLE_SAME_DOC |
         nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
 
   if (scrollFrame) {
     nsIFrame* capturingFrame = scrollFrame->GetScrolledFrame();
     if (capturingFrame) {
-      nsPoint pt =
-        nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, capturingFrame);
+      nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent,
+                                                                capturingFrame);
       frameselection->StartAutoScrollTimer(capturingFrame, pt, 30);
     }
   }
 
   return NS_OK;
 }
 
 /**
@@ -3053,17 +3061,17 @@ HandleFrameSelection(nsFrameSelection*  
         return rv;
       }
     } else if (aParentContentForTableSel) {
       aFrameSelection->SetMouseDownState(false);
       rv = aFrameSelection->HandleTableSelection(
                               aParentContentForTableSel,
                               aContentOffsetForTableSel,
                               aTargetForTableSel,
-                              static_cast<WidgetMouseEvent*>(aEvent));
+                              aEvent->AsMouseEvent());
       if (NS_FAILED(rv)) {
         return rv;
       }
     }
     aFrameSelection->SetDelayedCaretData(0);
   }
 
   aFrameSelection->SetMouseDownState(false);
@@ -3109,17 +3117,17 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsP
 
       if (!mouseDown && frameselection->HasDelayedCaretData() &&
           frameselection->GetClickCountInDelayedCaretData() < 2) {
         nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
         offsets = GetContentOffsetsFromPoint(pt, SKIP_HIDDEN);
         handleTableSelection = false;
       } else {
         GetDataForTableSelection(frameselection, PresContext()->PresShell(),
-                                 static_cast<WidgetMouseEvent*>(aEvent),
+                                 aEvent->AsMouseEvent(),
                                  getter_AddRefs(parentContent),
                                  &contentOffsetForTableSel,
                                  &targetForTableSel);
       }
     }
   }
 
   // We might be capturing in some other document and the event just happened to
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -687,19 +687,17 @@ NS_METHOD nsHTMLFramesetFrame::HandleEve
   NS_ENSURE_ARG_POINTER(aEventStatus);
   if (mDragger) {
     // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
     switch (aEvent->message) {
       case NS_MOUSE_MOVE:
         MouseDrag(aPresContext, aEvent);
 	      break;
       case NS_MOUSE_BUTTON_UP:
-        if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-            static_cast<WidgetMouseEvent*>(aEvent)->button ==
-              WidgetMouseEvent::eLeftButton) {
+        if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
           EndMouseDrag(aPresContext);
         }
 	      break;
     }
     *aEventStatus = nsEventStatus_eConsumeNoDefault;
   } else {
     *aEventStatus = nsEventStatus_eIgnore;
   }
@@ -1585,20 +1583,18 @@ nsHTMLFramesetBorderFrame::HandleEvent(n
   NS_ENSURE_ARG_POINTER(aEventStatus);
   *aEventStatus = nsEventStatus_eIgnore;
 
   //XXX Mouse setting logic removed.  The remaining logic should also move.
   if (!mCanResize) {
     return NS_OK;
   }
 
-  if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-      aEvent->message == NS_MOUSE_BUTTON_DOWN &&
-      static_cast<WidgetMouseEvent*>(aEvent)->button ==
-        WidgetMouseEvent::eLeftButton) {
+  if (aEvent->message == NS_MOUSE_BUTTON_DOWN &&
+      aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
     nsHTMLFramesetFrame* parentFrame = do_QueryFrame(GetParent());
     if (parentFrame) {
       parentFrame->StartMouseDrag(aPresContext, this, aEvent);
       *aEventStatus = nsEventStatus_eConsumeNoDefault;
     }
   }
   return NS_OK;
 }
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1631,20 +1631,18 @@ nsImageFrame::GetContentForEvent(WidgetE
 // XXX what should clicks on transparent pixels do?
 NS_IMETHODIMP
 nsImageFrame::HandleEvent(nsPresContext* aPresContext,
                           WidgetGUIEvent* aEvent,
                           nsEventStatus* aEventStatus)
 {
   NS_ENSURE_ARG_POINTER(aEventStatus);
 
-  if ((aEvent->eventStructType == NS_MOUSE_EVENT &&
-       aEvent->message == NS_MOUSE_BUTTON_UP && 
-       static_cast<WidgetMouseEvent*>(aEvent)->button ==
-         WidgetMouseEvent::eLeftButton) ||
+  if ((aEvent->message == NS_MOUSE_BUTTON_UP && 
+       aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) ||
       aEvent->message == NS_MOUSE_MOVE) {
     nsImageMap* map = GetImageMap();
     bool isServerMap = IsServerImageMap();
     if ((nullptr != map) || isServerMap) {
       nsIntPoint p;
       TranslateEventCoords(
         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this), p);
       bool inside = false;
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -420,63 +420,57 @@ nsMenuFrame::HandleEvent(nsPresContext* 
     // On other platforms, toggle menulist on unmodified F4 or Alt arrow
     if ((keyCode == NS_VK_F4 && !keyEvent->IsAlt()) ||
         ((keyCode == NS_VK_UP || keyCode == NS_VK_DOWN) && keyEvent->IsAlt())) {
       *aEventStatus = nsEventStatus_eConsumeNoDefault;
       ToggleMenuState();
     }
 #endif
   }
-  else if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-           aEvent->message == NS_MOUSE_BUTTON_DOWN &&
-           static_cast<WidgetMouseEvent*>(aEvent)->button ==
-             WidgetMouseEvent::eLeftButton &&
+  else if (aEvent->message == NS_MOUSE_BUTTON_DOWN &&
+           aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
            !IsDisabled() && IsMenu()) {
     // The menu item was selected. Bring up the menu.
     // We have children.
     // Don't prevent the default action here, since that will also cancel
     // potential drag starts.
     if (!mMenuParent || mMenuParent->IsMenuBar()) {
       ToggleMenuState();
     }
     else {
       if (!IsOpen()) {
         OpenMenu(false);
       }
     }
   }
   else if (
 #ifndef NSCONTEXTMENUISMOUSEUP
-           (aEvent->eventStructType == NS_MOUSE_EVENT &&
-            aEvent->message == NS_MOUSE_BUTTON_UP &&
-            static_cast<WidgetMouseEvent*>(aEvent)->button ==
-              WidgetMouseEvent::eRightButton) &&
+           (aEvent->message == NS_MOUSE_BUTTON_UP &&
+            aEvent->AsMouseEvent()->button == WidgetMouseEvent::eRightButton) &&
 #else
-            aEvent->message == NS_CONTEXTMENU &&
+           aEvent->message == NS_CONTEXTMENU &&
 #endif
-            onmenu && !IsMenu() && !IsDisabled()) {
+           onmenu && !IsMenu() && !IsDisabled()) {
     // if this menu is a context menu it accepts right-clicks...fire away!
     // Make sure we cancel default processing of the context menu event so
     // that it doesn't bubble and get seen again by the popuplistener and show
     // another context menu.
     //
     // Furthermore (there's always more, isn't there?), on some platforms (win32
     // being one of them) we get the context menu event on a mouse up while
     // on others we get it on a mouse down. For the ones where we get it on a
     // mouse down, we must continue listening for the right button up event to
     // dismiss the menu.
     if (mMenuParent->IsContextMenu()) {
       *aEventStatus = nsEventStatus_eConsumeNoDefault;
       Execute(aEvent);
     }
   }
-  else if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-           aEvent->message == NS_MOUSE_BUTTON_UP &&
-           static_cast<WidgetMouseEvent*>(aEvent)->button ==
-             WidgetMouseEvent::eLeftButton &&
+  else if (aEvent->message == NS_MOUSE_BUTTON_UP &&
+           aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
            !IsMenu() && !IsDisabled()) {
     // Execute the execute event handler.
     *aEventStatus = nsEventStatus_eConsumeNoDefault;
     Execute(aEvent);
   }
   else if (aEvent->message == NS_MOUSE_EXIT_SYNTH) {
     // Kill our timer if one is active.
     if (mOpenTimer) {
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -62,19 +62,17 @@ nsResizerFrame::HandleEvent(nsPresContex
   nsWeakFrame weakFrame(this);
   bool doDefault = true;
 
   switch (aEvent->message) {
     case NS_TOUCH_START:
     case NS_MOUSE_BUTTON_DOWN: {
       if (aEvent->eventStructType == NS_TOUCH_EVENT ||
           (aEvent->eventStructType == NS_MOUSE_EVENT &&
-        static_cast<WidgetMouseEvent*>(aEvent)->button ==
-          WidgetMouseEvent::eLeftButton))
-      {
+           aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton)) {
         nsCOMPtr<nsIBaseWindow> window;
         nsIPresShell* presShell = aPresContext->GetPresShell();
         nsIContent* contentToResize =
           GetContentToResize(presShell, getter_AddRefs(window));
         if (contentToResize) {
           nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
           if (!frameToResize)
             break;
@@ -127,22 +125,19 @@ nsResizerFrame::HandleEvent(nsPresContex
 
         nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
       }
     }
     break;
 
   case NS_TOUCH_END:
   case NS_MOUSE_BUTTON_UP: {
-
-      if (aEvent->eventStructType == NS_TOUCH_EVENT ||
-          (aEvent->eventStructType == NS_MOUSE_EVENT &&
-           static_cast<WidgetMouseEvent*>(aEvent)->button ==
-             WidgetMouseEvent::eLeftButton))
-    {
+    if (aEvent->eventStructType == NS_TOUCH_EVENT ||
+        (aEvent->eventStructType == NS_MOUSE_EVENT &&
+         aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton)) {
       // we're done tracking.
       mTrackingMouseMove = false;
 
       nsIPresShell::SetCapturingContent(nullptr, 0);
 
       doDefault = false;
     }
   }
@@ -291,20 +286,17 @@ nsResizerFrame::HandleEvent(nsPresContex
   case NS_MOUSE_CLICK:
     if (aEvent->IsLeftClickEvent())
     {
       MouseClicked(aPresContext, aEvent);
     }
     break;
 
   case NS_MOUSE_DOUBLECLICK:
-    if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-        static_cast<WidgetMouseEvent*>(aEvent)->button ==
-          WidgetMouseEvent::eLeftButton)
-    {
+    if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
       nsCOMPtr<nsIBaseWindow> window;
       nsIPresShell* presShell = aPresContext->GetPresShell();
       nsIContent* contentToResize =
         GetContentToResize(presShell, getter_AddRefs(window));
       if (contentToResize) {
         nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(contentToResize->GetPrimaryFrame());
         if (menuPopupFrame)
           break; // Don't restore original sizing for menupopup frames until
--- a/layout/xul/base/src/nsScrollbarButtonFrame.cpp
+++ b/layout/xul/base/src/nsScrollbarButtonFrame.cpp
@@ -81,17 +81,17 @@ nsScrollbarButtonFrame::HandleEvent(nsPr
 
 bool
 nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
                                           WidgetGUIEvent* aEvent,
                                           nsEventStatus* aEventStatus)
 {
   // Get the desired action for the scrollbar button.
   LookAndFeel::IntID tmpAction;
-  uint16_t button = static_cast<WidgetMouseEvent*>(aEvent)->button;
+  uint16_t button = aEvent->AsMouseEvent()->button;
   if (button == WidgetMouseEvent::eLeftButton) {
     tmpAction = LookAndFeel::eIntID_ScrollButtonLeftMouseButtonAction;
   } else if (button == WidgetMouseEvent::eMiddleButton) {
     tmpAction = LookAndFeel::eIntID_ScrollButtonMiddleMouseButtonAction;
   } else if (button == WidgetMouseEvent::eRightButton) {
     tmpAction = LookAndFeel::eIntID_ScrollButtonRightMouseButtonAction;
   } else {
     return false;
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -942,17 +942,17 @@ bool
 nsSliderFrame::ShouldScrollForEvent(WidgetGUIEvent* aEvent)
 {
   switch (aEvent->message) {
     case NS_TOUCH_START:
     case NS_TOUCH_END:
       return true;
     case NS_MOUSE_BUTTON_DOWN:
     case NS_MOUSE_BUTTON_UP: {
-      uint16_t button = static_cast<WidgetMouseEvent*>(aEvent)->button;
+      uint16_t button = aEvent->AsMouseEvent()->button;
       return (button == WidgetMouseEvent::eLeftButton) ||
              (button == WidgetMouseEvent::eMiddleButton && gMiddlePref);
     }
     default:
       return false;
   }
 }
 
@@ -973,17 +973,17 @@ nsSliderFrame::ShouldScrollToClickForEve
 
 #ifdef XP_MACOSX
   // On Mac, clicking the scrollbar thumb should never scroll to click.
   if (IsEventOverThumb(aEvent)) {
     return false;
   }
 #endif
 
-  WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
+  WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
 #ifdef XP_MACOSX
     bool invertPref = mouseEvent->IsAlt();
 #else
     bool invertPref = mouseEvent->IsShift();
 #endif
     return GetScrollToClick() != invertPref;
   }
--- a/layout/xul/base/src/nsSplitterFrame.cpp
+++ b/layout/xul/base/src/nsSplitterFrame.cpp
@@ -387,19 +387,17 @@ nsSplitterFrame::HandleEvent(nsPresConte
   nsWeakFrame weakFrame(this);
   nsRefPtr<nsSplitterFrameInner> kungFuDeathGrip(mInner);
   switch (aEvent->message) {
     case NS_MOUSE_MOVE: 
       mInner->MouseDrag(aPresContext, aEvent);
     break;
   
     case NS_MOUSE_BUTTON_UP:
-      if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-          static_cast<WidgetMouseEvent*>(aEvent)->button ==
-            WidgetMouseEvent::eLeftButton) {
+      if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
         mInner->MouseUp(aPresContext, aEvent);
       }
     break;
   }
 
   NS_ENSURE_STATE(weakFrame.IsAlive());
   return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
 }
--- a/layout/xul/base/src/nsTitleBarFrame.cpp
+++ b/layout/xul/base/src/nsTitleBarFrame.cpp
@@ -65,19 +65,17 @@ nsTitleBarFrame::HandleEvent(nsPresConte
     return NS_OK;
   }
 
   bool doDefault = true;
 
   switch (aEvent->message) {
 
    case NS_MOUSE_BUTTON_DOWN:  {
-       if (aEvent->eventStructType == NS_MOUSE_EVENT &&
-           static_cast<WidgetMouseEvent*>(aEvent)->button ==
-             WidgetMouseEvent::eLeftButton) {
+       if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
          // titlebar has no effect in non-chrome shells
          nsCOMPtr<nsISupports> cont = aPresContext->GetContainer();
          nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
          if (dsti) {
            int32_t type = -1;
            if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
                type == nsIDocShellTreeItem::typeChrome) {
              // we're tracking.
@@ -94,19 +92,18 @@ nsTitleBarFrame::HandleEvent(nsPresConte
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
          doDefault = false;
        }
      }
      break;
 
 
    case NS_MOUSE_BUTTON_UP: {
-       if(mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT &&
-          static_cast<WidgetMouseEvent*>(aEvent)->button ==
-            WidgetMouseEvent::eLeftButton) {
+       if (mTrackingMouseMove &&
+           aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
          // we're done tracking.
          mTrackingMouseMove = false;
 
          // end capture
          nsIPresShell::SetCapturingContent(nullptr, 0);
 
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
          doDefault = false;
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -699,18 +699,17 @@ void
 nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent,
                              nsView* aView,
                              nsEventStatus* aStatus)
 {
   PROFILER_LABEL("event", "nsViewManager::DispatchEvent");
 
   if ((aEvent->HasMouseEventMessage() &&
        // Ignore mouse events that we synthesize.
-       static_cast<WidgetMouseEvent*>(aEvent)->reason ==
-         WidgetMouseEvent::eReal &&
+       aEvent->AsMouseEvent()->reason == WidgetMouseEvent::eReal &&
        // Ignore mouse exit and enter (we'll get moves if the user
        // is really moving the mouse) since we get them when we
        // create and destroy widgets.
        aEvent->message != NS_MOUSE_EXIT &&
        aEvent->message != NS_MOUSE_ENTER) ||
       aEvent->HasKeyEventMessage() ||
       aEvent->HasIMEEventMessage() ||
       aEvent->message == NS_PLUGIN_INPUT_EVENT) {
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6132,21 +6132,20 @@ nsWindow::BeginResizeDrag(WidgetGUIEvent
 {
     NS_ENSURE_ARG_POINTER(aEvent);
 
     if (aEvent->eventStructType != NS_MOUSE_EVENT) {
         // you can only begin a resize drag with a mouse event
         return NS_ERROR_INVALID_ARG;
     }
 
-    WidgetMouseEvent* mouse_event = static_cast<WidgetMouseEvent*>(aEvent);
-
     GdkWindow *gdk_window;
     gint button, screenX, screenY;
-    if (!GetDragInfo(mouse_event, &gdk_window, &button, &screenX, &screenY)) {
+    if (!GetDragInfo(aEvent->AsMouseEvent(), &gdk_window, &button,
+                     &screenX, &screenY)) {
         return NS_ERROR_FAILURE;
     }
 
     // work out what GdkWindowEdge we're talking about
     GdkWindowEdge window_edge;
     if (aVertical < 0) {
         if (aHorizontal < 0) {
             window_edge = GDK_WINDOW_EDGE_NORTH_WEST;
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2742,19 +2742,17 @@ nsWindow::BeginResizeDrag(WidgetGUIEvent
 {
     NS_ENSURE_ARG_POINTER(aEvent);
 
     if (aEvent->eventStructType != NS_MOUSE_EVENT) {
         // you can only begin a resize drag with a mouse event
         return NS_ERROR_INVALID_ARG;
     }
 
-    WidgetMouseEvent* mouse_event = static_cast<WidgetMouseEvent*>(aEvent);
-
-    if (mouse_event->button != WidgetMouseEvent::eLeftButton) {
+    if (aEvent->AsMouseEvent()->button != WidgetMouseEvent::eLeftButton) {
         // you can only begin a resize drag with the left mouse button
         return NS_ERROR_INVALID_ARG;
     }
 
     return NS_OK;
 }
 
 nsEventStatus
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -1510,18 +1510,17 @@ nsWindow::BeginResizeDrag(WidgetGUIEvent
 {
   NS_ENSURE_ARG_POINTER(aEvent);
 
   if (aEvent->eventStructType != NS_MOUSE_EVENT) {
     // you can only begin a resize drag with a mouse event
     return NS_ERROR_INVALID_ARG;
   }
 
-  WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
-  if (mouseEvent->button != WidgetMouseEvent::eLeftButton) {
+  if (aEvent->AsMouseEvent()->button != WidgetMouseEvent::eLeftButton) {
     // you can only begin a resize drag with the left mouse button
     return NS_ERROR_INVALID_ARG;
   }
 
   // work out what sizemode we're talking about
   WPARAM syscommand;
   if (aVertical < 0) {
     if (aHorizontal < 0) {