Bug 920425 part.2 Implement mozilla::WidgetEvent::As*Event() methods r=roc
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 18 Oct 2013 15:10:20 +0900
changeset 165113 f20b704a6727d82d35cc75d17f35c8dc4a3a7450
parent 165112 8ee916cacd478cc3969410dc80e6e6982a6f79dd
child 165114 081e788525f92752c0eed6022077976b027eed14
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
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.2 Implement mozilla::WidgetEvent::As*Event() methods r=roc
content/events/public/MutationEvent.h
widget/BasicEvents.h
widget/ContentEvents.h
widget/MiscEvents.h
widget/MouseEvents.h
widget/TextEvents.h
widget/TouchEvents.h
widget/shared/WidgetEventImpl.cpp
--- a/content/events/public/MutationEvent.h
+++ b/content/events/public/MutationEvent.h
@@ -11,16 +11,18 @@
 #include "nsIAtom.h"
 #include "nsIDOMNode.h"
 
 namespace mozilla {
 
 class InternalMutationEvent : public WidgetEvent
 {
 public:
+  virtual InternalMutationEvent* AsMutationEvent() MOZ_OVERRIDE { return this; }
+
   InternalMutationEvent(bool aIsTrusted, uint32_t aMessage) :
     WidgetEvent(aIsTrusted, aMessage, NS_MUTATION_EVENT),
     mAttrChange(0)
   {
     mFlags.mCancelable = false;
   }
 
   nsCOMPtr<nsIDOMNode> mRelatedNode;
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -617,17 +617,17 @@ public:
   {
     MOZ_COUNT_CTOR(WidgetEvent);
     mFlags.Clear();
     mFlags.mIsTrusted = aIsTrusted;
     mFlags.mCancelable = true;
     mFlags.mBubbles = true;
   }
 
-  ~WidgetEvent()
+  virtual ~WidgetEvent()
   {
     MOZ_COUNT_DTOR(WidgetEvent);
   }
 
   WidgetEvent(const WidgetEvent& aOther)
   {
     MOZ_COUNT_CTOR(WidgetEvent);
     *this = aOther;
@@ -672,16 +672,30 @@ public:
     originalTarget = aCopyTargets ? aEvent.originalTarget : nullptr;
   }
 
   /**
    * Utils for checking event types
    */
 
   /**
+   * As*Event() returns the pointer of the instance only when the instance is
+   * the class or one of its derived class.
+   */
+#define NS_ROOT_EVENT_CLASS(aPrefix, aName)
+#define NS_EVENT_CLASS(aPrefix, aName) \
+  virtual aPrefix##aName* As##aName(); \
+  const aPrefix##aName* As##aName() const;
+
+#include "mozilla/EventClassList.h"
+
+#undef NS_EVENT_CLASS
+#undef NS_ROOT_EVENT_CLASS
+
+  /**
    * Returns true if the event is WidgetInputEvent or inherits it.
    */
   bool IsInputDerivedEvent() const;
   /**
    * Returns true if the event is WidgetMouseEvent or inherits it.
    */
   bool IsMouseDerivedEvent() const;
   /**
@@ -800,16 +814,18 @@ protected:
   }
 
   WidgetGUIEvent() :
     pluginEvent(nullptr)
   {
   }
 
 public:
+  virtual WidgetGUIEvent* AsGUIEvent() MOZ_OVERRIDE { return this; }
+
   WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetEvent(aIsTrusted, aMessage, NS_GUI_EVENT),
     widget(aWidget), pluginEvent(nullptr)
   {
   }
 
   /// Originator of the event
   nsCOMPtr<nsIWidget> widget;
@@ -887,16 +903,18 @@ protected:
   {
   }
 
   WidgetInputEvent()
   {
   }
 
 public:
+  virtual WidgetInputEvent* AsInputEvent() MOZ_OVERRIDE { return this; }
+
   WidgetInputEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_INPUT_EVENT),
     modifiers(0)
   {
   }
 
   // true indicates the shift key is down
   bool IsShift() const
@@ -1001,16 +1019,18 @@ protected:
   InternalUIEvent(bool aIsTrusted, uint32_t aMessage,
                   nsEventStructType aStructType, int32_t aDetail) :
     WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aStructType),
     detail(aDetail)
   {
   }
 
 public:
+  virtual InternalUIEvent* AsUIEvent() MOZ_OVERRIDE { return this; }
+
   InternalUIEvent(bool aIsTrusted, uint32_t aMessage, int32_t aDetail) :
     WidgetGUIEvent(aIsTrusted, aMessage, nullptr, NS_UI_EVENT),
     detail(aDetail)
   {
   }
 
   int32_t detail;
 
--- a/widget/ContentEvents.h
+++ b/widget/ContentEvents.h
@@ -21,16 +21,21 @@ namespace mozilla {
 
 /******************************************************************************
  * mozilla::InternalScriptErrorEvent
  ******************************************************************************/
 
 class InternalScriptErrorEvent : public WidgetEvent
 {
 public:
+  virtual InternalScriptErrorEvent* AsScriptErrorEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   InternalScriptErrorEvent(bool aIsTrusted, uint32_t aMessage) :
     WidgetEvent(aIsTrusted, aMessage, NS_SCRIPT_ERROR_EVENT),
     lineNr(0), errorMsg(nullptr), fileName(nullptr)
   {
   }
 
   int32_t           lineNr;
   const PRUnichar*  errorMsg;
@@ -53,16 +58,21 @@ public:
 
 /******************************************************************************
  * mozilla::InternalScrollPortEvent
  ******************************************************************************/
 
 class InternalScrollPortEvent : public WidgetGUIEvent
 {
 public:
+  virtual InternalScrollPortEvent* AsScrollPortEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   enum orientType
   {
     vertical   = 0,
     horizontal = 1,
     both       = 2
   };
 
   InternalScrollPortEvent(bool aIsTrusted, uint32_t aMessage,
@@ -85,16 +95,21 @@ public:
 
 /******************************************************************************
  * mozilla::InternalScrollPortEvent
  ******************************************************************************/
 
 class InternalScrollAreaEvent : public WidgetGUIEvent
 {
 public:
+  virtual InternalScrollAreaEvent* AsScrollAreaEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   InternalScrollAreaEvent(bool aIsTrusted, uint32_t aMessage,
                           nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_SCROLLAREA_EVENT)
   {
   }
 
   nsRect mArea;
 
@@ -112,16 +127,18 @@ public:
  *
  * We hold the originating form control for form submit and reset events.
  * originator is a weak pointer (does not hold a strong reference).
  ******************************************************************************/
 
 class InternalFormEvent : public WidgetEvent
 {
 public:
+  virtual InternalFormEvent* AsFormEvent() MOZ_OVERRIDE { return this; }
+
   InternalFormEvent(bool aIsTrusted, uint32_t aMessage) :
     WidgetEvent(aIsTrusted, aMessage, NS_FORM_EVENT),
     originator(nullptr)
   {
   }
 
   nsIContent *originator;
 
@@ -135,16 +152,21 @@ public:
 
 /******************************************************************************
  * mozilla::InternalClipboardEvent
  ******************************************************************************/
 
 class InternalClipboardEvent : public WidgetEvent
 {
 public:
+  virtual InternalClipboardEvent* AsClipboardEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   InternalClipboardEvent(bool aIsTrusted, uint32_t aMessage) :
     WidgetEvent(aIsTrusted, aMessage, NS_CLIPBOARD_EVENT)
   {
   }
 
   nsCOMPtr<nsIDOMDataTransfer> clipboardData;
 
   void AssignClipboardEventData(const InternalClipboardEvent& aEvent,
@@ -158,16 +180,18 @@ public:
 
 /******************************************************************************
  * mozilla::InternalFocusEvent
  ******************************************************************************/
 
 class InternalFocusEvent : public InternalUIEvent
 {
 public:
+  virtual InternalFocusEvent* AsFocusEvent() MOZ_OVERRIDE { return this; }
+
   InternalFocusEvent(bool aIsTrusted, uint32_t aMessage) :
     InternalUIEvent(aIsTrusted, aMessage, NS_FOCUS_EVENT, 0),
     fromRaise(false), isRefocus(false)
   {
   }
 
   /// The possible related target
   nsCOMPtr<dom::EventTarget> relatedTarget;
@@ -187,16 +211,21 @@ public:
 
 /******************************************************************************
  * mozilla::InternalTransitionEvent
  ******************************************************************************/
 
 class InternalTransitionEvent : public WidgetEvent
 {
 public:
+  virtual InternalTransitionEvent* AsTransitionEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   InternalTransitionEvent(bool aIsTrusted, uint32_t aMessage,
                           const nsAString& aPropertyName, float aElapsedTime,
                           const nsAString& aPseudoElement) :
     WidgetEvent(aIsTrusted, aMessage, NS_TRANSITION_EVENT),
     propertyName(aPropertyName), elapsedTime(aElapsedTime),
     pseudoElement(aPseudoElement)
   {
   }
@@ -217,16 +246,21 @@ public:
 
 /******************************************************************************
  * mozilla::InternalAnimationEvent
  ******************************************************************************/
 
 class InternalAnimationEvent : public WidgetEvent
 {
 public:
+  virtual InternalAnimationEvent* AsAnimationEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   InternalAnimationEvent(bool aIsTrusted, uint32_t aMessage,
                          const nsAString& aAnimationName, float aElapsedTime,
                          const nsAString& aPseudoElement) :
     WidgetEvent(aIsTrusted, aMessage, NS_ANIMATION_EVENT),
     animationName(aAnimationName), elapsedTime(aElapsedTime),
     pseudoElement(aPseudoElement)
   {
   }
--- a/widget/MiscEvents.h
+++ b/widget/MiscEvents.h
@@ -17,16 +17,21 @@ namespace mozilla {
 
 /******************************************************************************
  * mozilla::WidgetContentCommandEvent
  ******************************************************************************/
 
 class WidgetContentCommandEvent : public WidgetGUIEvent
 {
 public:
+  virtual WidgetContentCommandEvent* AsContentCommandEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetContentCommandEvent(bool aIsTrusted, uint32_t aMessage,
                             nsIWidget* aWidget,
                             bool aOnlyEnabledCheck = false) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_CONTENT_COMMAND_EVENT),
     mOnlyEnabledCheck(aOnlyEnabledCheck), mSucceeded(false), mIsEnabled(false)
   {
   }
 
@@ -67,16 +72,18 @@ public:
  * in focused content, you should use WidgetContentCommandEvent instead.
  *
  * XXX Should be |WidgetChromeCommandEvent|?
  ******************************************************************************/
 
 class WidgetCommandEvent : public WidgetGUIEvent
 {
 public:
+  virtual WidgetCommandEvent* AsCommandEvent() MOZ_OVERRIDE { return this; }
+
   WidgetCommandEvent(bool aIsTrusted, nsIAtom* aEventType,
                      nsIAtom* aCommand, nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, NS_USER_DEFINED_EVENT, aWidget,
                    NS_COMMAND_EVENT),
     command(aCommand)
   {
     userType = aEventType;
   }
@@ -97,16 +104,18 @@ public:
  * mozilla::WidgetPluginEvent
  *
  * This event delivers only a native event to focused plugin.
  ******************************************************************************/
 
 class WidgetPluginEvent : public WidgetGUIEvent
 {
 public:
+  virtual WidgetPluginEvent* AsPluginEvent() MOZ_OVERRIDE { return this; }
+
   WidgetPluginEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_PLUGIN_EVENT),
     retargetToFocusedDocument(false)
   {
   }
 
   // If true, this event needs to be retargeted to focused document.
   // Otherwise, never retargeted. Defaults to false.
--- a/widget/MouseEvents.h
+++ b/widget/MouseEvents.h
@@ -41,29 +41,32 @@ namespace dom {
  ******************************************************************************/
 
 class WidgetMouseEventBase : public WidgetInputEvent
 {
 private:
   friend class dom::PBrowserParent;
   friend class dom::PBrowserChild;
 
-public:
+protected:
   WidgetMouseEventBase()
   {
   }
 
   WidgetMouseEventBase(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
                        nsEventStructType aStructType) :
     WidgetInputEvent(aIsTrusted, aMessage, aWidget, aStructType),
     button(0), buttons(0), pressure(0),
     inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
  {
  }
 
+public:
+  virtual WidgetMouseEventBase* AsMouseEventBase() MOZ_OVERRIDE { return this; }
+
   /// The possible related target
   nsCOMPtr<nsISupports> relatedTarget;
 
   enum buttonType
   {
     eLeftButton   = 0,
     eMiddleButton = 1,
     eRightButton  = 2
@@ -131,21 +134,21 @@ public:
   };
 
   enum exitType
   {
     eChild,
     eTopLevel
   };
 
+protected:
   WidgetMouseEvent()
   {
   }
 
-protected:
   WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
                    nsEventStructType aStructType, reasonType aReason) :
     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aStructType),
     acceptActivation(false), ignoreRootScrollFrame(false),
     reason(aReason), context(eNormal), exit(eChild), clickCount(0)
   {
     switch (aMessage) {
       case NS_MOUSE_MOVE:
@@ -157,16 +160,17 @@ protected:
         mFlags.mCancelable = false;
         break;
       default:
         break;
     }
   }
 
 public:
+  virtual WidgetMouseEvent* AsMouseEvent() MOZ_OVERRIDE { return this; }
 
   WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
                    reasonType aReason, contextType aContext = eNormal) :
     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_EVENT),
     acceptActivation(false), ignoreRootScrollFrame(false),
     reason(aReason), context(aContext), exit(eChild), clickCount(0)
   {
     switch (aMessage) {
@@ -182,17 +186,18 @@ public:
         button = (context == eNormal) ? eRightButton : eLeftButton;
         break;
       default:
         break;
     }
   }
 
 #ifdef DEBUG
-  ~WidgetMouseEvent() {
+  virtual ~WidgetMouseEvent()
+  {
     NS_WARN_IF_FALSE(message != NS_CONTEXTMENU ||
                      button ==
                        ((context == eNormal) ? eRightButton : eLeftButton),
                      "Wrong button set to NS_CONTEXTMENU event?");
   }
 #endif
 
   // Special return code for MOUSE_ACTIVATE to signal.
@@ -220,16 +225,18 @@ public:
 
 /******************************************************************************
  * mozilla::WidgetDragEvent
  ******************************************************************************/
 
 class WidgetDragEvent : public WidgetMouseEvent
 {
 public:
+  virtual WidgetDragEvent* AsDragEvent() MOZ_OVERRIDE { return this; }
+
   WidgetDragEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetMouseEvent(aIsTrusted, aMessage, aWidget, NS_DRAG_EVENT, eReal),
     userCancelled(false)
   {
     mFlags.mCancelable =
       (aMessage != NS_DRAGDROP_EXIT_SYNTH &&
        aMessage != NS_DRAGDROP_LEAVE_SYNTH &&
        aMessage != NS_DRAGDROP_END);
@@ -263,16 +270,21 @@ public:
 class WidgetMouseScrollEvent : public WidgetMouseEventBase
 {
 private:
   WidgetMouseScrollEvent()
   {
   }
 
 public:
+  virtual WidgetMouseScrollEvent* AsMouseScrollEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetMouseScrollEvent(bool aIsTrusted, uint32_t aMessage,
                          nsIWidget* aWidget) :
     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_SCROLL_EVENT),
     delta(0), isHorizontal(false)
   {
   }
 
   // The delta value of mouse scroll event.
@@ -307,16 +319,18 @@ private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
 
   WidgetWheelEvent()
   {
   }
 
 public:
+  virtual WidgetWheelEvent* AsWheelEvent() MOZ_OVERRIDE { return this; }
+
   WidgetWheelEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT),
     deltaX(0.0), deltaY(0.0), deltaZ(0.0),
     deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
     customizedByUserPrefs(false), isMomentum(false), isPixelOnlyDevice(false),
     lineOrPageDeltaX(0), lineOrPageDeltaY(0), scrollType(SCROLL_DEFAULT),
     overflowDeltaX(0.0), overflowDeltaY(0.0),
     mViewPortIsOverscrolled(false)
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -65,21 +65,23 @@ struct AlternativeCharCode
  ******************************************************************************/
 
 class WidgetKeyboardEvent : public WidgetInputEvent
 {
 private:
   friend class dom::PBrowserParent;
   friend class dom::PBrowserChild;
 
-public:
   WidgetKeyboardEvent()
   {
   }
 
+public:
+  virtual WidgetKeyboardEvent* AsKeyboardEvent() MOZ_OVERRIDE { return this; }
+
   WidgetKeyboardEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetInputEvent(aIsTrusted, aMessage, aWidget, NS_KEY_EVENT),
     keyCode(0), charCode(0),
     location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), isChar(0),
     mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified),
     mNativeKeyEvent(nullptr),
     mUniqueId(0)
   {
@@ -309,16 +311,18 @@ private:
   WidgetTextEvent()
   {
   }
 
 public:
   uint32_t seqno;
 
 public:
+  virtual WidgetTextEvent* AsTextEvent() MOZ_OVERRIDE { return this; }
+
   WidgetTextEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_TEXT_EVENT),
     rangeCount(0), rangeArray(nullptr), isChar(false)
   {
   }
 
   // The composition string or the commit string.
   nsString theText;
@@ -358,16 +362,21 @@ private:
   WidgetCompositionEvent()
   {
   }
 
 public:
   uint32_t seqno;
 
 public:
+  virtual WidgetCompositionEvent* AsCompositionEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetCompositionEvent(bool aIsTrusted, uint32_t aMessage,
                          nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_COMPOSITION_EVENT)
   {
     // XXX compositionstart is cancelable in draft of DOM3 Events.
     //     However, it doesn't make sense for us, we cannot cancel composition
     //     when we send compositionstart event.
     mFlags.mCancelable = false;
@@ -398,16 +407,21 @@ private:
   friend class dom::PBrowserChild;
 
   WidgetQueryContentEvent()
   {
     MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
   }
 
 public:
+  virtual WidgetQueryContentEvent* AsQueryContentEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetQueryContentEvent(bool aIsTrusted, uint32_t aMessage,
                           nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_QUERY_CONTENT_EVENT),
     mSucceeded(false), mWasAsync(false)
   {
   }
 
   void InitForQueryTextContent(uint32_t aOffset, uint32_t aLength)
@@ -508,16 +522,21 @@ private:
   {
     MOZ_CRASH("WidgetSelectionEvent is created without proper arguments");
   }
 
 public:
   uint32_t seqno;
 
 public:
+  virtual WidgetSelectionEvent* AsSelectionEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetSelectionEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_SELECTION_EVENT),
     mExpandToClusterBoundary(true), mSucceeded(false)
   {
   }
 
   // Start offset of selection
   uint32_t mOffset;
--- a/widget/TouchEvents.h
+++ b/widget/TouchEvents.h
@@ -26,16 +26,21 @@ namespace mozilla {
  * The event is dispatched to the layout and based on what is underneath
  * the initial contact point it's then decided if we should pan
  * (finger scrolling) or drag the target element.
  ******************************************************************************/
 
 class WidgetGestureNotifyEvent : public WidgetGUIEvent
 {
 public:
+  virtual WidgetGestureNotifyEvent* AsGestureNotifyEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetGestureNotifyEvent(bool aIsTrusted, uint32_t aMessage,
                            nsIWidget *aWidget) :
     WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_GESTURENOTIFY_EVENT),
     panDirection(ePanNone), displayPanFeedback(false)
   {
   }
 
   enum ePanDirection
@@ -62,16 +67,21 @@ public:
 
 /******************************************************************************
  * mozilla::WidgetTouchEvent
  ******************************************************************************/
 
 class WidgetSimpleGestureEvent : public WidgetMouseEventBase
 {
 public:
+  virtual WidgetSimpleGestureEvent* AsSimpleGestureEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   WidgetSimpleGestureEvent(bool aIsTrusted, uint32_t aMessage,
                            nsIWidget* aWidget, uint32_t aDirection,
                            double aDelta) :
     WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
                          NS_SIMPLE_GESTURE_EVENT),
     allowedDirections(0), direction(aDirection), delta(aDelta), clickCount(0)
   {
   }
@@ -109,16 +119,18 @@ public:
 
 /******************************************************************************
  * mozilla::WidgetTouchEvent
  ******************************************************************************/
 
 class WidgetTouchEvent : public WidgetInputEvent
 {
 public:
+  virtual WidgetTouchEvent* AsTouchEvent() MOZ_OVERRIDE { return this; }
+
   WidgetTouchEvent()
   {
   }
 
   WidgetTouchEvent(bool aIsTrusted, WidgetTouchEvent* aEvent) :
     WidgetInputEvent(aIsTrusted, aEvent->message, aEvent->widget,
                      NS_TOUCH_EVENT)
   {
@@ -129,17 +141,17 @@ public:
   }
 
   WidgetTouchEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetInputEvent(aIsTrusted, aMessage, aWidget, NS_TOUCH_EVENT)
   {
     MOZ_COUNT_CTOR(WidgetTouchEvent);
   }
 
-  ~WidgetTouchEvent()
+  virtual ~WidgetTouchEvent()
   {
     MOZ_COUNT_DTOR(WidgetTouchEvent);
   }
 
   nsTArray<nsRefPtr<mozilla::dom::Touch>> touches;
 
   void AssignTouchEventData(const WidgetTouchEvent& aEvent, bool aCopyTargets)
   {
--- a/widget/shared/WidgetEventImpl.cpp
+++ b/widget/shared/WidgetEventImpl.cpp
@@ -1,48 +1,62 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/BasicEvents.h"
+#include "mozilla/ContentEvents.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/MutationEvent.h"
+#include "mozilla/TextEvents.h"
+#include "mozilla/TouchEvents.h"
 
 namespace mozilla {
 
 /******************************************************************************
+ * As*Event() implementation
+ ******************************************************************************/
+
+#define NS_ROOT_EVENT_CLASS(aPrefix, aName)
+#define NS_EVENT_CLASS(aPrefix, aName) \
+aPrefix##aName* \
+WidgetEvent::As##aName() \
+{ \
+  return nullptr; \
+} \
+\
+const aPrefix##aName* \
+WidgetEvent::As##aName() const \
+{ \
+  return const_cast<WidgetEvent*>(this)->As##aName(); \
+}
+
+#include "mozilla/EventClassList.h"
+
+#undef NS_EVENT_CLASS
+#undef NS_ROOT_EVENT_CLASS
+
+/******************************************************************************
  * mozilla::WidgetEvent
  *
  * Event struct type checking methods.
  ******************************************************************************/
 
 bool
 WidgetEvent::IsInputDerivedEvent() const
 {
-  switch (eventStructType) {
-    case NS_INPUT_EVENT:
-    case NS_MOUSE_EVENT:
-    case NS_KEY_EVENT:
-    case NS_TOUCH_EVENT:
-    case NS_DRAG_EVENT:
-    case NS_MOUSE_SCROLL_EVENT:
-    case NS_WHEEL_EVENT:
-    case NS_SIMPLE_GESTURE_EVENT:
-      return true;
-    default:
-      return false;
-  }
+  return AsInputEvent() != nullptr;
 }
 
 bool
 WidgetEvent::IsMouseDerivedEvent() const
 {
-  return eventStructType == NS_MOUSE_EVENT ||
-         eventStructType == NS_DRAG_EVENT;
+  return AsMouseEvent() != nullptr;
 }
 
 bool
 WidgetEvent::IsQueryContentEvent() const
 {
   return eventStructType == NS_QUERY_CONTENT_EVENT;
 }
 
@@ -150,43 +164,41 @@ WidgetEvent::HasPluginActivationEventMes
  * mozilla::WidgetEvent
  *
  * Specific event checking methods.
  ******************************************************************************/
 
 bool
 WidgetEvent::IsLeftClickEvent() const
 {
-  return eventStructType == NS_MOUSE_EVENT &&
-         message == NS_MOUSE_CLICK &&
-         static_cast<const WidgetMouseEvent*>(this)->button ==
-           WidgetMouseEvent::eLeftButton;
+  const WidgetMouseEvent* mouseEvent = AsMouseEvent();
+  return mouseEvent && message == NS_MOUSE_CLICK &&
+         mouseEvent->button == WidgetMouseEvent::eLeftButton;
 }
 
 bool
 WidgetEvent::IsContextMenuKeyEvent() const
 {
-  return eventStructType == NS_MOUSE_EVENT &&
-         message == NS_CONTEXTMENU &&
-         static_cast<const WidgetMouseEvent*>(this)->context ==
-            WidgetMouseEvent::eContextMenuKey;
+  const WidgetMouseEvent* mouseEvent = AsMouseEvent();
+  return mouseEvent && message == NS_CONTEXTMENU &&
+         mouseEvent->context == WidgetMouseEvent::eContextMenuKey;
 }
 
 bool
 WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
 {
-  return IsNativeEventDelivererForPlugin() &&
-    static_cast<const WidgetPluginEvent*>(this)->retargetToFocusedDocument;
+  const WidgetPluginEvent* pluginEvent = AsPluginEvent();
+  return pluginEvent && pluginEvent->retargetToFocusedDocument;
 }
 
 bool
 WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const
 {
-  return IsNativeEventDelivererForPlugin() &&
-    !static_cast<const WidgetPluginEvent*>(this)->retargetToFocusedDocument;
+  const WidgetPluginEvent* pluginEvent = AsPluginEvent();
+  return pluginEvent && !pluginEvent->retargetToFocusedDocument;
 }
 
 bool
 WidgetEvent::IsIMERelatedEvent() const
 {
   return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
 }
 
@@ -223,24 +235,22 @@ WidgetEvent::IsAllowedToDispatchDOMEvent
 {
   switch (eventStructType) {
     case NS_MOUSE_EVENT:
       // We want synthesized mouse moves to cause mouseover and mouseout
       // DOM events (nsEventStateManager::PreHandleEvent), but not mousemove
       // DOM events.
       // Synthesized button up events also do not cause DOM events because they
       // do not have a reliable refPoint.
-      return static_cast<const WidgetMouseEvent*>(this)->reason ==
-               WidgetMouseEvent::eReal;
+      return AsMouseEvent()->reason == WidgetMouseEvent::eReal;
 
     case NS_WHEEL_EVENT: {
       // wheel event whose all delta values are zero by user pref applied, it
       // shouldn't cause a DOM event.
-      const WidgetWheelEvent* wheelEvent =
-        static_cast<const WidgetWheelEvent*>(this);
+      const WidgetWheelEvent* wheelEvent = AsWheelEvent();
       return wheelEvent->deltaX != 0.0 || wheelEvent->deltaY != 0.0 ||
              wheelEvent->deltaZ != 0.0;
     }
 
     default:
       return true;
   }
 }