Bug 1377020 - Use MOZ_DEFINE_ENUM instead of a sentinel enumerator for enumerations in gfx/layers. r=kats
authorBotond Ballo <botond@mozilla.com>
Fri, 30 Jun 2017 21:18:55 -0400
changeset 416221 484dcb23bd4d2bbbb82099c8514ca54736e9de41
parent 416220 6641837cae964ff5c2e2889f9bf93ed930a6bf0a
child 416222 78e4e9169cd893adda2e0462e72c55af73350efb
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1377020
milestone56.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 1377020 - Use MOZ_DEFINE_ENUM instead of a sentinel enumerator for enumerations in gfx/layers. r=kats MozReview-Commit-ID: IUQDb0VIAwQ
dom/ipc/TabChild.cpp
gfx/layers/FrameMetrics.h
gfx/layers/LayersTypes.h
gfx/layers/apz/public/GeckoContentController.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/AndroidDynamicToolbarAnimator.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/CheckerboardEvent.cpp
gfx/layers/apz/src/CheckerboardEvent.h
gfx/layers/apz/src/FocusState.cpp
gfx/layers/apz/src/FocusTarget.h
gfx/layers/apz/src/GestureEventListener.cpp
gfx/layers/apz/src/KeyboardScrollAction.cpp
gfx/layers/apz/src/KeyboardScrollAction.h
gfx/layers/apz/src/KeyboardScrollAnimation.cpp
gfx/layers/apz/src/TouchCounter.cpp
gfx/layers/apz/src/WheelScrollAnimation.cpp
gfx/layers/apz/test/gtest/APZTestCommon.h
gfx/layers/apz/util/APZCCallbackHelper.cpp
gfx/layers/apz/util/APZEventState.cpp
gfx/layers/apz/util/ChromeProcessController.cpp
gfx/layers/ipc/LayersMessageUtils.h
widget/InputData.h
widget/nsGUIEventIPC.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1364,21 +1364,16 @@ TabChild::RecvHandleTap(const GeckoConte
           aInputBlockId);
     }
     break;
   case GeckoContentController::TapType::eLongTapUp:
     if (mGlobal && mTabChildGlobal) {
       mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
     }
     break;
-  case GeckoContentController::TapType::eSentinel:
-    // Should never happen, but we need to handle this case to make the compiler
-    // happy.
-    MOZ_ASSERT(false);
-    break;
   }
   return IPC_OK();
 }
 
 bool
 TabChild::NotifyAPZStateChange(const ViewID& aViewId,
                                const layers::GeckoContentController::APZStateChange& aChange,
                                const int& aArg)
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_FRAMEMETRICS_H
 #define GFX_FRAMEMETRICS_H
 
 #include <stdint.h>                     // for uint32_t, uint64_t
 #include "Units.h"                      // for CSSRect, CSSPixel, etc
+#include "mozilla/DefineEnum.h"         // for MOZ_DEFINE_ENUM
 #include "mozilla/HashFunctions.h"      // for HashGeneric
 #include "mozilla/Maybe.h"
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Rect.h"           // for RoundedIn
 #include "mozilla/gfx/ScaleFactor.h"    // for ScaleFactor
 #include "mozilla/gfx/Logging.h"        // for Log
 #include "mozilla/StaticPtr.h"          // for StaticAutoPtr
 #include "mozilla/TimeStamp.h"          // for TimeStamp
@@ -45,33 +46,32 @@ struct FrameMetrics {
   friend struct IPC::ParamTraits<mozilla::layers::FrameMetrics>;
 public:
   // We use IDs to identify frames across processes.
   typedef uint64_t ViewID;
   static const ViewID NULL_SCROLL_ID;   // This container layer does not scroll.
   static const ViewID START_SCROLL_ID = 2;  // This is the ID that scrolling subframes
                                         // will begin at.
 
-  enum ScrollOffsetUpdateType : uint8_t {
-    eNone,          // The default; the scroll offset was not updated
-    eMainThread,    // The scroll offset was updated by the main thread.
-    ePending,       // The scroll offset was updated on the main thread, but not
-                    // painted, so the layer texture data is still at the old
-                    // offset.
-    eUserAction,    // In an APZ repaint request, this means the APZ generated
-                    // the scroll position based on user action (the alternative
-                    // is eNone which means it's just request a repaint because
-                    // it got a scroll update from the main thread).
-    eRestore,       // The scroll offset was updated by the main thread, but as
-                    // a restore from history or after a frame reconstruction.
-                    // In this case, APZ can ignore the offset change if the
-                    // user has done an APZ scroll already.
-
-    eSentinel       // For IPC use only
-  };
+  MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(
+    ScrollOffsetUpdateType, uint8_t, (
+      eNone,          // The default; the scroll offset was not updated
+      eMainThread,    // The scroll offset was updated by the main thread.
+      ePending,       // The scroll offset was updated on the main thread, but not
+                      // painted, so the layer texture data is still at the old
+                      // offset.
+      eUserAction,    // In an APZ repaint request, this means the APZ generated
+                      // the scroll position based on user action (the alternative
+                      // is eNone which means it's just request a repaint because
+                      // it got a scroll update from the main thread).
+      eRestore        // The scroll offset was updated by the main thread, but as
+                      // a restore from history or after a frame reconstruction.
+                      // In this case, APZ can ignore the offset change if the
+                      // user has done an APZ scroll already.
+  ));
 
   FrameMetrics()
     : mScrollId(NULL_SCROLL_ID)
     , mPresShellResolution(1)
     , mCompositionBounds(0, 0, 0, 0)
     , mDisplayPort(0, 0, 0, 0)
     , mCriticalDisplayPort(0, 0, 0, 0)
     , mScrollableRect(0, 0, 0, 0)
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSTYPES_H
 #define GFX_LAYERSTYPES_H
 
 #include <stdint.h>                     // for uint32_t
 
 #include "Units.h"
+#include "mozilla/DefineEnum.h"         // for MOZ_DEFINE_ENUM
 #include "mozilla/gfx/Point.h"          // for IntPoint
 #include "mozilla/Maybe.h"
 #include "mozilla/TypedEnumBits.h"
 #include "nsRegion.h"
 
 #include <stdio.h>            // FILE
 #include "mozilla/Logging.h"            // for PR_LOG
 
@@ -67,22 +68,22 @@ enum class DrawRegionClip : int8_t {
 
 enum class SurfaceMode : int8_t {
   SURFACE_NONE = 0,
   SURFACE_OPAQUE,
   SURFACE_SINGLE_CHANNEL_ALPHA,
   SURFACE_COMPONENT_ALPHA
 };
 
-enum class ScaleMode : int8_t {
-  SCALE_NONE,
-  STRETCH,
-  SENTINEL
+MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
+  ScaleMode, int8_t, (
+    SCALE_NONE,
+    STRETCH
 // Unimplemented - PRESERVE_ASPECT_RATIO_CONTAIN
-};
+));
 
 struct EventRegions {
   // The hit region for a layer contains all areas on the layer that are
   // sensitive to events. This region is an over-approximation and may
   // contain regions that are not actually sensitive, but any such regions
   // will be included in the mDispatchToContentHitRegion.
   nsIntRegion mHitRegion;
   // The mDispatchToContentHitRegion for a layer contains all areas for
@@ -299,22 +300,21 @@ public:
   }
   uint64_t Value() const {
     return mHandle;
   }
 private:
   uint64_t mHandle;
 };
 
-enum class ScrollDirection : uint32_t {
+MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint32_t, (
   NONE,
   VERTICAL,
-  HORIZONTAL,
-  SENTINEL /* for IPC serialization */
-};
+  HORIZONTAL
+));
 
 enum class CSSFilterType : int8_t {
   BLUR,
   BRIGHTNESS,
   CONTRAST,
   GRAYSCALE,
   HUE_ROTATE,
   INVERT,
--- a/gfx/layers/apz/public/GeckoContentController.h
+++ b/gfx/layers/apz/public/GeckoContentController.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_layers_GeckoContentController_h
 #define mozilla_layers_GeckoContentController_h
 
 #include "FrameMetrics.h"               // for FrameMetrics, etc
 #include "InputData.h"                  // for PinchGestureInput
 #include "Units.h"                      // for CSSPoint, CSSRect, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
+#include "mozilla/DefineEnum.h"         // for MOZ_DEFINE_ENUM
 #include "mozilla/EventForwards.h"      // for Modifiers
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 
 class Runnable;
 
 namespace layers {
@@ -44,25 +45,24 @@ public:
    * if the user moves their finger after triggering the long-tap but before
    * lifting it).
    * The difference between eDoubleTap and eSecondTap is subtle - the eDoubleTap
    * is for an actual double-tap "gesture" while eSecondTap is for the same user
    * input but where a double-tap gesture is not allowed. This is used to fire
    * a click event with detail=2 to web content (similar to what a mouse double-
    * click would do).
    */
-  enum class TapType {
-    eSingleTap,
-    eDoubleTap,
-    eSecondTap,
-    eLongTap,
-    eLongTapUp,
-
-    eSentinel,
-  };
+  MOZ_DEFINE_ENUM_CLASS_AT_CLASS_SCOPE(
+    TapType, (
+      eSingleTap,
+      eDoubleTap,
+      eSecondTap,
+      eLongTap,
+      eLongTapUp
+  ));
 
   /**
    * Requests handling of a tap event. |aPoint| is in LD pixels, relative to the
    * current scroll offset.
    */
   virtual void HandleTap(TapType aType,
                          const LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
@@ -102,44 +102,42 @@ public:
    */
   virtual bool IsRepaintThread() = 0;
 
   /**
    * Runs the given task on the "repaint" thread.
    */
   virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) = 0;
 
-  enum class APZStateChange {
-    /**
-     * APZ started modifying the view (including panning, zooming, and fling).
-     */
-    eTransformBegin,
-    /**
-     * APZ finished modifying the view.
-     */
-    eTransformEnd,
-    /**
-     * APZ started a touch.
-     * |aArg| is 1 if touch can be a pan, 0 otherwise.
-     */
-    eStartTouch,
-    /**
-     * APZ started a pan.
-     */
-    eStartPanning,
-    /**
-     * APZ finished processing a touch.
-     * |aArg| is 1 if touch was a click, 0 otherwise.
-     */
-    eEndTouch,
+  MOZ_DEFINE_ENUM_CLASS_AT_CLASS_SCOPE(
+    APZStateChange, (
+      /**
+       * APZ started modifying the view (including panning, zooming, and fling).
+       */
+      eTransformBegin,
+      /**
+       * APZ finished modifying the view.
+       */
+      eTransformEnd,
+      /**
+       * APZ started a touch.
+       * |aArg| is 1 if touch can be a pan, 0 otherwise.
+       */
+      eStartTouch,
+      /**
+       * APZ started a pan.
+       */
+      eStartPanning,
+      /**
+       * APZ finished processing a touch.
+       * |aArg| is 1 if touch was a click, 0 otherwise.
+       */
+      eEndTouch
+  ));
 
-    // Sentinel value for IPC, this must be the last item in the enum and
-    // should not be used as an actual message value.
-    eSentinel
-  };
   /**
    * General notices of APZ state changes for consumers.
    * |aGuid| identifies the APZC originating the state change.
    * |aChange| identifies the type of state change
    * |aArg| is used by some state changes to pass extra information (see
    *        the documentation for each state change above)
    */
   virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1300,20 +1300,16 @@ APZCTreeManager::ReceiveInputEvent(Input
           break;
         }
         case KeyboardScrollAction::eScrollLine:
         case KeyboardScrollAction::eScrollPage:
         case KeyboardScrollAction::eScrollComplete: {
           targetGuid = mFocusState.GetVerticalTarget();
           break;
         }
-
-        case KeyboardScrollAction::eSentinel: {
-          MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType");
-        }
       }
 
       // If we don't have a scroll target then either we have a stale focus target,
       // the focused element has event listeners, or the focused element doesn't have a
       // layerized scroll frame. In any case we need to dispatch to content.
       if (!targetGuid) {
         APZ_KEY_LOG("Skipping key input with no current focus target\n");
         return result;
@@ -1343,19 +1339,16 @@ APZCTreeManager::ReceiveInputEvent(Input
       // Any keyboard event that is dispatched to the input queue at this point
       // should have been consumed
       MOZ_ASSERT(result == nsEventStatus_eConsumeNoDefault);
 
       keyInput.mHandledByAPZ = true;
       focusSetter.MarkAsNonFocusChanging();
 
       break;
-    } case SENTINEL_INPUT: {
-      MOZ_ASSERT_UNREACHABLE("Invalid InputType.");
-      break;
     }
   }
   return result;
 }
 
 static TouchBehaviorFlags
 ConvertToTouchBehavior(HitTestResult result)
 {
--- a/gfx/layers/apz/src/AndroidDynamicToolbarAnimator.cpp
+++ b/gfx/layers/apz/src/AndroidDynamicToolbarAnimator.cpp
@@ -126,18 +126,16 @@ AndroidDynamicToolbarAnimator::ReceiveIn
   switch (multiTouch.mType) {
   case MultiTouchInput::MULTITOUCH_START:
     mControllerTouchCount = multiTouch.mTouches.Length();
     break;
   case MultiTouchInput::MULTITOUCH_END:
   case MultiTouchInput::MULTITOUCH_CANCEL:
     mControllerTouchCount -= multiTouch.mTouches.Length();
     break;
-  case MultiTouchInput::MULTITOUCH_SENTINEL:
-    MOZ_FALLTHROUGH_ASSERT("Invalid value");
   case MultiTouchInput::MULTITOUCH_MOVE:
     break;
   }
 
   if (mControllerTouchCount > 1) {
     mControllerResetOnNextMove = true;
   }
 
@@ -198,19 +196,16 @@ AndroidDynamicToolbarAnimator::ReceiveIn
   }
   case MultiTouchInput::MULTITOUCH_END:
   case MultiTouchInput::MULTITOUCH_CANCEL:
     // last finger was lifted
     if (mControllerTouchCount == 0) {
       HandleTouchEnd(currentToolbarState, currentTouch);
     }
     break;
-  case MultiTouchInput::MULTITOUCH_SENTINEL:
-    MOZ_ASSERT_UNREACHABLE("Invalid value");
-    break;
   }
 
   TranslateTouchEvent(multiTouch);
 
   return status;
 }
 
 void
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -944,17 +944,16 @@ nsEventStatus AsyncPanZoomController::Ha
       }
     }
 
     switch (multiTouchInput.mType) {
       case MultiTouchInput::MULTITOUCH_START: rv = OnTouchStart(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_MOVE: rv = OnTouchMove(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_END: rv = OnTouchEnd(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_CANCEL: rv = OnTouchCancel(multiTouchInput); break;
-      case MultiTouchInput::MULTITOUCH_SENTINEL: MOZ_ASSERT_UNREACHABLE("Invalid value"); break;
     }
     break;
   }
   case PANGESTURE_INPUT: {
     PanGestureInput panGestureInput = aEvent.AsPanGestureInput();
     if (!panGestureInput.TransformToLocal(aTransformToApzc)) {
       return rv;
     }
@@ -963,17 +962,16 @@ nsEventStatus AsyncPanZoomController::Ha
       case PanGestureInput::PANGESTURE_MAYSTART: rv = OnPanMayBegin(panGestureInput); break;
       case PanGestureInput::PANGESTURE_CANCELLED: rv = OnPanCancelled(panGestureInput); break;
       case PanGestureInput::PANGESTURE_START: rv = OnPanBegin(panGestureInput); break;
       case PanGestureInput::PANGESTURE_PAN: rv = OnPan(panGestureInput, true); break;
       case PanGestureInput::PANGESTURE_END: rv = OnPanEnd(panGestureInput); break;
       case PanGestureInput::PANGESTURE_MOMENTUMSTART: rv = OnPanMomentumStart(panGestureInput); break;
       case PanGestureInput::PANGESTURE_MOMENTUMPAN: rv = OnPan(panGestureInput, false); break;
       case PanGestureInput::PANGESTURE_MOMENTUMEND: rv = OnPanMomentumEnd(panGestureInput); break;
-      case PanGestureInput::PANGESTURE_SENTINEL: MOZ_ASSERT_UNREACHABLE("Invalid value"); break;
     }
     break;
   }
   case MOUSE_INPUT: {
     MouseInput mouseInput = aEvent.AsMouseInput();
     if (!mouseInput.TransformToLocal(aTransformToApzc)) {
       return rv;
     }
@@ -1006,20 +1004,16 @@ nsEventStatus AsyncPanZoomController::Ha
     rv = HandleGestureEvent(tapInput);
     break;
   }
   case KEYBOARD_INPUT: {
     KeyboardInput keyInput = aEvent.AsKeyboardInput();
     rv = OnKeyboard(keyInput);
     break;
   }
-  case SENTINEL_INPUT: {
-    MOZ_ASSERT_UNREACHABLE("Invalid value");
-    break;
-  }
   }
 
   return rv;
 }
 
 nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent)
 {
   APZThreadUtils::AssertOnControllerThread();
@@ -1028,31 +1022,29 @@ nsEventStatus AsyncPanZoomController::Ha
 
   switch (aEvent.mInputType) {
   case PINCHGESTURE_INPUT: {
     const PinchGestureInput& pinchGestureInput = aEvent.AsPinchGestureInput();
     switch (pinchGestureInput.mType) {
       case PinchGestureInput::PINCHGESTURE_START: rv = OnScaleBegin(pinchGestureInput); break;
       case PinchGestureInput::PINCHGESTURE_SCALE: rv = OnScale(pinchGestureInput); break;
       case PinchGestureInput::PINCHGESTURE_END: rv = OnScaleEnd(pinchGestureInput); break;
-      case PinchGestureInput::PINCHGESTURE_SENTINEL: MOZ_ASSERT_UNREACHABLE("Invalid value"); break;
     }
     break;
   }
   case TAPGESTURE_INPUT: {
     const TapGestureInput& tapGestureInput = aEvent.AsTapGestureInput();
     switch (tapGestureInput.mType) {
       case TapGestureInput::TAPGESTURE_LONG: rv = OnLongPress(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_LONG_UP: rv = OnLongPressUp(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_UP: rv = OnSingleTapUp(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_CONFIRMED: rv = OnSingleTapConfirmed(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_DOUBLE: rv = OnDoubleTap(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_SECOND: rv = OnSecondTap(tapGestureInput); break;
       case TapGestureInput::TAPGESTURE_CANCEL: rv = OnCancelTap(tapGestureInput); break;
-      case TapGestureInput::TAPGESTURE_SENTINEL: MOZ_ASSERT_UNREACHABLE("Invalid value"); break;
     }
     break;
   }
   default: MOZ_ASSERT_UNREACHABLE("Unhandled input event"); break;
   }
 
   return rv;
 }
@@ -1605,20 +1597,16 @@ AsyncPanZoomController::GetScrollWheelDe
       delta.x = aEvent.mDeltaX * pageScrollSize.width;
       delta.y = aEvent.mDeltaY * pageScrollSize.height;
       break;
     }
     case ScrollWheelInput::SCROLLDELTA_PIXEL: {
       delta = ToParentLayerCoordinates(ScreenPoint(aEvent.mDeltaX, aEvent.mDeltaY), aEvent.mOrigin);
       break;
     }
-    case ScrollWheelInput::SCROLLDELTA_SENTINEL: {
-      MOZ_ASSERT_UNREACHABLE("Invalid value");
-      break;
-    }
   }
 
   // Apply user-set multipliers.
   delta.x *= aEvent.mUserDeltaMultiplierX;
   delta.y *= aEvent.mUserDeltaMultiplierY;
 
   // For the conditions under which we allow system scroll overrides, see
   // EventStateManager::DeltaAccumulator::ComputeScrollAmountForDefaultAction
@@ -1682,20 +1670,16 @@ void ReportKeyboardScrollAction(const Ke
     case KeyboardScrollAction::eScrollPage: {
       scrollMethod = ScrollInputMethod::ApzScrollPage;
       break;
     }
     case KeyboardScrollAction::eScrollComplete: {
       scrollMethod = ScrollInputMethod::ApzCompleteScroll;
       break;
     }
-    case KeyboardScrollAction::eSentinel: {
-      MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollAction.");
-      return;
-    }
   }
 
   mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
       (uint32_t)scrollMethod);
 }
 
 nsEventStatus
 AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
@@ -1811,18 +1795,16 @@ AsyncPanZoomController::GetKeyboardDesti
     case KeyboardScrollAction::eScrollComplete: {
       if (aAction.mForward) {
         scrollDestination.y = scrollRect.YMost();
       } else {
         scrollDestination.y = scrollRect.y;
       }
       break;
     }
-    case KeyboardScrollAction::eSentinel:
-      MOZ_ASSERT_UNREACHABLE("unexpected keyboard delta type");
   }
 
   return scrollDestination;
 }
 
 // Return whether or not the underlying layer can be scrolled on either axis.
 bool
 AsyncPanZoomController::CanScroll(const InputData& aEvent) const
@@ -1858,17 +1840,16 @@ bool
 AsyncPanZoomController::CanScroll(ScrollDirection aDirection) const
 {
   ReentrantMonitorAutoEnter lock(mMonitor);
   switch (aDirection) {
   case ScrollDirection::HORIZONTAL: return mX.CanScroll();
   case ScrollDirection::VERTICAL:   return mY.CanScroll();
 
   case ScrollDirection::NONE:
-  case ScrollDirection::SENTINEL:
     MOZ_ASSERT_UNREACHABLE("Invalid value");
     break;
   }
   return false;
 }
 
 bool
 AsyncPanZoomController::AllowScrollHandoffInCurrentBlock() const
@@ -1902,18 +1883,16 @@ ScrollInputMethodForWheelDeltaType(Scrol
       return ScrollInputMethod::ApzWheelLine;
     }
     case ScrollWheelInput::SCROLLDELTA_PAGE: {
       return ScrollInputMethod::ApzWheelPage;
     }
     case ScrollWheelInput::SCROLLDELTA_PIXEL: {
       return ScrollInputMethod::ApzWheelPixel;
     }
-    case ScrollWheelInput::SCROLLDELTA_SENTINEL:
-      break;
   }
   MOZ_ASSERT_UNREACHABLE("Invalid value");
   return ScrollInputMethod::ApzWheelLine;
 }
 
 nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
 {
   ParentLayerPoint delta = GetScrollWheelDelta(aEvent);
@@ -2018,21 +1997,16 @@ nsEventStatus AsyncPanZoomController::On
       // conversion so that the scroll duration isn't affected by zoom
       nsPoint velocity =
         CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
 
       WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
       animation->UpdateDelta(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
       break;
     }
-
-    case ScrollWheelInput::SCROLLMODE_SENTINEL: {
-      MOZ_ASSERT_UNREACHABLE("Invalid ScrollMode.");
-      break;
-    }
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 void
 AsyncPanZoomController::NotifyMozMouseScrollEvent(const nsString& aString) const
 {
--- a/gfx/layers/apz/src/CheckerboardEvent.cpp
+++ b/gfx/layers/apz/src/CheckerboardEvent.cpp
@@ -154,17 +154,17 @@ CheckerboardEvent::StartEvent()
   mCheckerboardingActive = true;
   mStartTime = TimeStamp::Now();
 
   if (!mRecordTrace) {
     return;
   }
   MonitorAutoLock lock(mRendertraceLock);
   std::vector<PropertyValue> history;
-  for (int i = 0; i < MAX_RendertraceProperty; i++) {
+  for (size_t i = 0; i < sRendertracePropertyCount; i++) {
     mBufferedProperties[i].Flush(history, lock);
   }
   std::sort(history.begin(), history.end());
   for (const PropertyValue& p : history) {
     LogInfo(p.mProperty, p.mTimeStamp, p.mRect, p.mExtraInfo, lock);
   }
   mRendertraceInfo << " -- checkerboarding starts below --" << std::endl;
 }
--- a/gfx/layers/apz/src/CheckerboardEvent.h
+++ b/gfx/layers/apz/src/CheckerboardEvent.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
 #ifndef mozilla_layers_CheckerboardEvent_h
 #define mozilla_layers_CheckerboardEvent_h
 
+#include "mozilla/DefineEnum.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 #include <sstream>
 #include "Units.h"
 #include <vector>
 
 namespace mozilla {
 namespace layers {
@@ -20,29 +21,27 @@ namespace layers {
  * a contiguous set of frames where a given APZC was checkerboarding. The intent
  * of this class is to record enough information that it can provide actionable
  * steps to reduce the occurrence of checkerboarding. Furthermore, it records
  * information about the severity of the checkerboarding so as to allow
  * prioritizing the debugging of some checkerboarding events over others.
  */
 class CheckerboardEvent {
 public:
-  enum RendertraceProperty {
-    Page,
-    PaintedCriticalDisplayPort,
-    PaintedDisplayPort,
-    RequestedDisplayPort,
-    UserVisible,
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    RendertraceProperty, (
+      Page,
+      PaintedCriticalDisplayPort,
+      PaintedDisplayPort,
+      RequestedDisplayPort,
+      UserVisible
+  ));
 
-    // sentinel final value
-    MAX_RendertraceProperty
-  };
-
-  static const char* sDescriptions[MAX_RendertraceProperty];
-  static const char* sColors[MAX_RendertraceProperty];
+  static const char* sDescriptions[sRendertracePropertyCount];
+  static const char* sColors[sRendertracePropertyCount];
 
 public:
   explicit CheckerboardEvent(bool aRecordTrace);
 
   /**
    * Gets the "severity" of the checkerboard event. This doesn't have units,
    * it's just useful for comparing two checkerboard events to see which one
    * is worse, for some implementation-specific definition of "worse".
@@ -202,17 +201,17 @@ private:
    * or mRendertraceInfo.
    */
   mutable Monitor mRendertraceLock;
   /**
    * A circular buffer to store some properties. This is used before the
    * checkerboarding actually starts, so that we have some data on what
    * was happening before the checkerboarding started.
    */
-  PropertyBuffer mBufferedProperties[MAX_RendertraceProperty];
+  PropertyBuffer mBufferedProperties[sRendertracePropertyCount];
   /**
    * The rendertrace info buffer that gives us info on what was happening
    * during the checkerboard event.
    */
   std::ostringstream mRendertraceInfo;
 };
 
 } // namespace layers
--- a/gfx/layers/apz/src/FocusState.cpp
+++ b/gfx/layers/apz/src/FocusState.cpp
@@ -108,19 +108,16 @@ FocusState::Update(uint64_t aRootLayerTr
       case FocusTarget::eNone: {
         FS_LOG("Setting target to nil (reached a nil target)\n");
 
         // Mark what sequence number this target has for debugging purposes so
         // we can always accurately report on whether we are stale or not
         mLastContentProcessedEvent = target.mSequenceNumber;
         return;
       }
-      case FocusTarget::eSentinel: {
-        MOZ_ASSERT_UNREACHABLE("Invalid FocusTargetType");
-      }
     }
   }
 }
 
 std::unordered_set<uint64_t>
 FocusState::GetFocusTargetLayerIds() const
 {
   std::unordered_set<uint64_t> layersIds;
--- a/gfx/layers/apz/src/FocusTarget.h
+++ b/gfx/layers/apz/src/FocusTarget.h
@@ -3,17 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_FocusTarget_h
 #define mozilla_layers_FocusTarget_h
 
 #include <stdint.h> // for int32_t, uint32_t
 
-#include "FrameMetrics.h" // for FrameMetrics::ViewID
+#include "FrameMetrics.h"        // for FrameMetrics::ViewID
+#include "mozilla/DefineEnum.h"  // for MOZ_DEFINE_ENUM
 
 class nsIPresShell;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * This class is used for communicating information about the currently focused
@@ -25,25 +26,23 @@ class FocusTarget final
 {
 public:
   struct ScrollTargets
   {
     FrameMetrics::ViewID mHorizontal;
     FrameMetrics::ViewID mVertical;
   };
 
-  enum FocusTargetType
-  {
-    eNone,
-    eRefLayer,
-    eScrollLayer,
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    FocusTargetType, (
+      eNone,
+      eRefLayer,
+      eScrollLayer
+  ));
 
-    // Used as an upper bound for ContiguousEnumSerializer
-    eSentinel,
-  };
   union FocusTargetData
   {
     uint64_t      mRefLayerId;
     ScrollTargets mScrollTargets;
   };
 
   FocusTarget();
 
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -141,19 +141,16 @@ nsEventStatus GestureEventListener::Hand
     }
 
     rv = HandleInputTouchEnd();
     break;
   case MultiTouchInput::MULTITOUCH_CANCEL:
     mTouches.Clear();
     rv = HandleInputTouchCancel();
     break;
-  case MultiTouchInput::MULTITOUCH_SENTINEL:
-    MOZ_ASSERT_UNREACHABLE("Invalid MultTouchInput.");
-    break;
   }
 
   return rv;
 }
 
 int32_t GestureEventListener::GetLastTouchIdentifier() const
 {
   if (mTouches.Length() != 1) {
--- a/gfx/layers/apz/src/KeyboardScrollAction.cpp
+++ b/gfx/layers/apz/src/KeyboardScrollAction.cpp
@@ -15,19 +15,16 @@ KeyboardScrollAction::GetScrollUnit(Keyb
     case KeyboardScrollAction::eScrollCharacter:
       return nsIScrollableFrame::LINES;
     case KeyboardScrollAction::eScrollLine:
       return nsIScrollableFrame::LINES;
     case KeyboardScrollAction::eScrollPage:
       return nsIScrollableFrame::PAGES;
     case KeyboardScrollAction::eScrollComplete:
       return nsIScrollableFrame::WHOLE;
-    case KeyboardScrollAction::eSentinel:
-      MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
-      return nsIScrollableFrame::WHOLE;
   }
 
   // Silence an overzealous warning
   return nsIScrollableFrame::WHOLE;
 }
 
 KeyboardScrollAction::KeyboardScrollAction()
   : mType(KeyboardScrollAction::eScrollCharacter)
--- a/gfx/layers/apz/src/KeyboardScrollAction.h
+++ b/gfx/layers/apz/src/KeyboardScrollAction.h
@@ -1,37 +1,35 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
 #ifndef mozilla_layers_KeyboardScrollAction_h
 #define mozilla_layers_KeyboardScrollAction_h
 
+#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
 #include "nsIScrollableFrame.h" // for nsIScrollableFrame::ScrollUnit
 
 namespace mozilla {
 namespace layers {
 
 /**
  * This class represents a scrolling action to be performed on a scrollable layer.
  */
 struct KeyboardScrollAction final
 {
 public:
-  enum KeyboardScrollActionType : uint8_t
-  {
-    eScrollCharacter,
-    eScrollLine,
-    eScrollPage,
-    eScrollComplete,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    eSentinel,
-  };
+  MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(
+    KeyboardScrollActionType, uint8_t, (
+      eScrollCharacter,
+      eScrollLine,
+      eScrollPage,
+      eScrollComplete
+  ));
 
   static nsIScrollableFrame::ScrollUnit
   GetScrollUnit(KeyboardScrollActionType aDeltaType);
 
   KeyboardScrollAction();
   KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward);
 
   // The type of scroll to perform for this action
--- a/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
@@ -28,19 +28,16 @@ KeyboardScrollAnimation::KeyboardScrollA
       mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
       break;
     }
     case KeyboardScrollAction::eScrollComplete: {
       mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
       mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
       break;
     }
-    case KeyboardScrollAction::eSentinel: {
-      MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
-    }
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
   mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
   mIntervalRatio = std::max(1.0, mIntervalRatio);
 }
 
 } // namespace layers
--- a/gfx/layers/apz/src/TouchCounter.cpp
+++ b/gfx/layers/apz/src/TouchCounter.cpp
@@ -32,19 +32,16 @@ TouchCounter::Update(const MultiTouchInp
         mActiveTouchCount = 0;
       }
       break;
     case MultiTouchInput::MULTITOUCH_CANCEL:
       mActiveTouchCount = 0;
       break;
     case MultiTouchInput::MULTITOUCH_MOVE:
       break;
-    case MultiTouchInput::MULTITOUCH_SENTINEL:
-      MOZ_ASSERT_UNREACHABLE("Invalid input");
-      break;
   }
 }
 
 uint32_t
 TouchCounter::GetActiveTouchCount() const
 {
   return mActiveTouchCount;
 }
--- a/gfx/layers/apz/src/WheelScrollAnimation.cpp
+++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp
@@ -24,18 +24,16 @@ WheelScrollAnimation::WheelScrollAnimati
   case ScrollWheelInput::SCROLLDELTA_PAGE:
     mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
     mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
     break;
   case ScrollWheelInput::SCROLLDELTA_PIXEL:
     mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
     mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
     break;
-  case ScrollWheelInput::SCROLLDELTA_SENTINEL:
-    MOZ_FALLTHROUGH_ASSERT("Invalid value");
   case ScrollWheelInput::SCROLLDELTA_LINE:
     mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
     mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
     break;
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
   mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h
+++ b/gfx/layers/apz/test/gtest/APZTestCommon.h
@@ -267,19 +267,16 @@ public:
       EXPECT_EQ(PANNING, mState);
       break;
     case ScrollDirection::HORIZONTAL:
       EXPECT_EQ(PANNING_LOCKED_X, mState);
       break;
     case ScrollDirection::VERTICAL:
       EXPECT_EQ(PANNING_LOCKED_Y, mState);
       break;
-    case ScrollDirection::SENTINEL:
-      MOZ_ASSERT(false, "Invalid value");
-      break;
     }
   }
 
   void AdvanceAnimationsUntilEnd(const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(10)) {
     while (AdvanceAnimations(mcc->Time())) {
       mcc->AdvanceBy(aIncrement);
     }
   }
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -970,19 +970,16 @@ APZCCallbackHelper::NotifyPinchGesture(P
       msg = eMagnifyGestureStart;
       break;
     case PinchGestureInput::PINCHGESTURE_SCALE:
       msg = eMagnifyGestureUpdate;
       break;
     case PinchGestureInput::PINCHGESTURE_END:
       msg = eMagnifyGesture;
       break;
-    case PinchGestureInput::PINCHGESTURE_SENTINEL:
-      MOZ_ASSERT_UNREACHABLE("Invalid value");
-      return;
   }
 
   WidgetSimpleGestureEvent event(true, msg, aWidget);
   event.mDelta = aSpanChange;
   event.mModifiers = aModifiers;
   DispatchWidgetEvent(event);
 }
 
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -485,21 +485,16 @@ APZEventState::ProcessAPZStateChange(Vie
     break;
   }
   case APZStateChange::eEndTouch:
   {
     mEndTouchIsClick = aArg;
     mActiveElementManager->HandleTouchEnd();
     break;
   }
-  case APZStateChange::eSentinel:
-    // Should never happen, but we want this case branch to stop the compiler
-    // whining about unhandled values.
-    MOZ_ASSERT(false);
-    break;
   }
 }
 
 void
 APZEventState::ProcessClusterHit()
 {
   // If we hit a cluster of links then we shouldn't activate any of them,
   // as we will be showing the zoomed view. (This is only called on Fennec).
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -212,21 +212,16 @@ ChromeProcessController::HandleTap(TapTy
     break;
   case TapType::eLongTap:
     mAPZEventState->ProcessLongTap(presShell, point, scale, aModifiers, aGuid,
         aInputBlockId);
     break;
   case TapType::eLongTapUp:
     mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
     break;
-  case TapType::eSentinel:
-    // Should never happen, but we need to handle this case branch for the
-    // compiler to be happy.
-    MOZ_ASSERT(false);
-    break;
   }
 }
 
 void
 ChromeProcessController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
                                             const ScrollableLayerGuid& aGuid,
                                             LayoutDeviceCoord aSpanChange,
                                             Modifiers aModifiers)
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -37,20 +37,20 @@ struct ParamTraits<mozilla::layers::Laye
   : public ContiguousEnumSerializer<
              mozilla::layers::LayersBackend,
              mozilla::layers::LayersBackend::LAYERS_NONE,
              mozilla::layers::LayersBackend::LAYERS_LAST>
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::ScaleMode>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::layers::ScaleMode,
              mozilla::layers::ScaleMode::SCALE_NONE,
-             mozilla::layers::ScaleMode::SENTINEL>
+             mozilla::layers::kHighestScaleMode>
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::TextureFlags>
   : public BitFlagsEnumSerializer<
             mozilla::layers::TextureFlags,
             mozilla::layers::TextureFlags::ALL_BITS>
 {};
@@ -59,28 +59,28 @@ template <>
 struct ParamTraits<mozilla::layers::DiagnosticTypes>
   : public BitFlagsEnumSerializer<
              mozilla::layers::DiagnosticTypes,
              mozilla::layers::DiagnosticTypes::ALL_BITS>
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::ScrollDirection>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
             mozilla::layers::ScrollDirection,
             mozilla::layers::ScrollDirection::NONE,
-            mozilla::layers::ScrollDirection::SENTINEL>
+            mozilla::layers::kHighestScrollDirection>
 {};
 
 template<>
 struct ParamTraits<mozilla::layers::FrameMetrics::ScrollOffsetUpdateType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::layers::FrameMetrics::ScrollOffsetUpdateType,
              mozilla::layers::FrameMetrics::ScrollOffsetUpdateType::eNone,
-             mozilla::layers::FrameMetrics::ScrollOffsetUpdateType::eSentinel>
+             mozilla::layers::FrameMetrics::sHighestScrollOffsetUpdateType>
 {};
 
 template<>
 struct ParamTraits<mozilla::layers::LayerHandle>
 {
   typedef mozilla::layers::LayerHandle paramType;
 
   static void Write(Message* msg, const paramType& param) {
@@ -436,20 +436,20 @@ struct ParamTraits<mozilla::layers::Focu
   {
     return ReadParam(aMsg, aIter, &aResult->mHorizontal) &&
            ReadParam(aMsg, aIter, &aResult->mVertical);
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::FocusTarget::FocusTargetType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::layers::FocusTarget::FocusTargetType,
              mozilla::layers::FocusTarget::eNone,
-             mozilla::layers::FocusTarget::eSentinel>
+             mozilla::layers::FocusTarget::sHighestFocusTargetType>
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::FocusTarget>
 {
   typedef mozilla::layers::FocusTarget paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -479,20 +479,20 @@ struct ParamTraits<mozilla::layers::Focu
     }
 
     return true;
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType,
              mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType::eScrollCharacter,
-             mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType::eSentinel>
+             mozilla::layers::KeyboardScrollAction::sHighestKeyboardScrollActionType>
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::KeyboardScrollAction>
 {
   typedef mozilla::layers::KeyboardScrollAction paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -552,34 +552,35 @@ struct ParamTraits<mozilla::layers::Keyb
     if (!ReadParam(aMsg, aIter, &shortcuts)) {
       return false;
     }
     *aResult = mozilla::layers::KeyboardMap(mozilla::Move(shortcuts));
     return true;
   }
 };
 
-typedef mozilla::layers::GeckoContentController::TapType TapType;
+typedef mozilla::layers::GeckoContentController GeckoContentController;
+typedef GeckoContentController::TapType TapType;
 
 template <>
 struct ParamTraits<TapType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              TapType,
              TapType::eSingleTap,
-             TapType::eSentinel>
+             GeckoContentController::sHighestTapType>
 {};
 
-typedef mozilla::layers::GeckoContentController::APZStateChange APZStateChange;
+typedef GeckoContentController::APZStateChange APZStateChange;
 
 template <>
 struct ParamTraits<APZStateChange>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              APZStateChange,
              APZStateChange::eTransformBegin,
-             APZStateChange::eSentinel>
+             GeckoContentController::sHighestAPZStateChange>
 {};
 
 template<>
 struct ParamTraits<mozilla::layers::EventRegionsOverride>
   : public BitFlagsEnumSerializer<
             mozilla::layers::EventRegionsOverride,
             mozilla::layers::EventRegionsOverride::ALL_BITS>
 {};
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -7,16 +7,17 @@
 #define InputData_h__
 
 #include "nsDebug.h"
 #include "nsIDOMWheelEvent.h"
 #include "nsIScrollableFrame.h"
 #include "nsPoint.h"
 #include "nsTArray.h"
 #include "Units.h"
+#include "mozilla/DefineEnum.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/MatrixFwd.h"
 #include "mozilla/layers/KeyboardScrollAction.h"
 
 template<class E> struct already_AddRefed;
 class nsIWidget;
 
@@ -26,31 +27,26 @@ namespace layers {
 class PAPZCTreeManagerParent;
 class APZCTreeManagerChild;
 }
 
 namespace dom {
 class Touch;
 } // namespace dom
 
-enum InputType
-{
-  // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-  // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-  MULTITOUCH_INPUT,
-  MOUSE_INPUT,
-  PANGESTURE_INPUT,
-  PINCHGESTURE_INPUT,
-  TAPGESTURE_INPUT,
-  SCROLLWHEEL_INPUT,
-  KEYBOARD_INPUT,
-
-  // Used as an upper bound for ContiguousEnumSerializer
-  SENTINEL_INPUT,
-};
+MOZ_DEFINE_ENUM(
+  InputType, (
+    MULTITOUCH_INPUT,
+    MOUSE_INPUT,
+    PANGESTURE_INPUT,
+    PINCHGESTURE_INPUT,
+    TAPGESTURE_INPUT,
+    SCROLLWHEEL_INPUT,
+    KEYBOARD_INPUT
+));
 
 class MultiTouchInput;
 class MouseInput;
 class PanGestureInput;
 class PinchGestureInput;
 class TapGestureInput;
 class ScrollWheelInput;
 class KeyboardInput;
@@ -186,28 +182,23 @@ public:
  * this copying from WidgetTouchEvent functionality can only be used on the main
  * thread.
  *
  * Stores an array of SingleTouchData.
  */
 class MultiTouchInput : public InputData
 {
 public:
-  enum MultiTouchType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-    MULTITOUCH_START,
-    MULTITOUCH_MOVE,
-    MULTITOUCH_END,
-    MULTITOUCH_CANCEL,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    MULTITOUCH_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    MultiTouchType, (
+      MULTITOUCH_START,
+      MULTITOUCH_MOVE,
+      MULTITOUCH_END,
+      MULTITOUCH_CANCEL
+  ));
 
   MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp,
                   Modifiers aModifiers);
   MultiTouchInput();
   MultiTouchInput(const MultiTouchInput& aOther);
   explicit MultiTouchInput(const WidgetTouchEvent& aTouchEvent);
   // This conversion from WidgetMouseEvent to MultiTouchInput is needed because
   // on the B2G emulator we can only receive mouse events, but we need to be
@@ -238,45 +229,36 @@ class MouseInput : public InputData
 {
 protected:
   friend mozilla::layers::PAPZCTreeManagerParent;
   friend mozilla::layers::APZCTreeManagerChild;
 
   MouseInput();
 
 public:
-  enum MouseType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-    MOUSE_NONE,
-    MOUSE_MOVE,
-    MOUSE_DOWN,
-    MOUSE_UP,
-    MOUSE_DRAG_START,
-    MOUSE_DRAG_END,
-    MOUSE_WIDGET_ENTER,
-    MOUSE_WIDGET_EXIT,
 
-    // Used as an upper bound for ContiguousEnumSerializer
-    MOUSE_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    MouseType, (
+      MOUSE_NONE,
+      MOUSE_MOVE,
+      MOUSE_DOWN,
+      MOUSE_UP,
+      MOUSE_DRAG_START,
+      MOUSE_DRAG_END,
+      MOUSE_WIDGET_ENTER,
+      MOUSE_WIDGET_EXIT
+  ));
 
-  enum ButtonType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-    LEFT_BUTTON,
-    MIDDLE_BUTTON,
-    RIGHT_BUTTON,
-    NONE,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    BUTTON_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    ButtonType, (
+      LEFT_BUTTON,
+      MIDDLE_BUTTON,
+      RIGHT_BUTTON,
+      NONE
+  ));
 
   MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource,
              int16_t aButtons, const ScreenPoint& aPoint, uint32_t aTime,
              TimeStamp aTimeStamp, Modifiers aModifiers);
   explicit MouseInput(const WidgetMouseEventBase& aMouseEvent);
 
   bool IsLeftButton() const;
 
@@ -302,67 +284,61 @@ class PanGestureInput : public InputData
 {
 protected:
   friend mozilla::layers::PAPZCTreeManagerParent;
   friend mozilla::layers::APZCTreeManagerChild;
 
   PanGestureInput();
 
 public:
-  enum PanGestureType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-
-    // MayStart: Dispatched before any actual panning has occurred but when a
-    // pan gesture is probably about to start, for example when the user
-    // starts touching the touchpad. Should interrupt any ongoing APZ
-    // animation and can be used to trigger scrollability indicators (e.g.
-    // flashing overlay scrollbars).
-    PANGESTURE_MAYSTART,
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    PanGestureType, (
+      // MayStart: Dispatched before any actual panning has occurred but when a
+      // pan gesture is probably about to start, for example when the user
+      // starts touching the touchpad. Should interrupt any ongoing APZ
+      // animation and can be used to trigger scrollability indicators (e.g.
+      // flashing overlay scrollbars).
+      PANGESTURE_MAYSTART,
 
-    // Cancelled: Dispatched after MayStart when no pan gesture is going to
-    // happen after all, for example when the user lifts their fingers from a
-    // touchpad without having done any scrolling.
-    PANGESTURE_CANCELLED,
+      // Cancelled: Dispatched after MayStart when no pan gesture is going to
+      // happen after all, for example when the user lifts their fingers from a
+      // touchpad without having done any scrolling.
+      PANGESTURE_CANCELLED,
 
-    // Start: A pan gesture is starting.
-    // For devices that do not support the MayStart event type, this event can
-    // be used to interrupt ongoing APZ animations.
-    PANGESTURE_START,
+      // Start: A pan gesture is starting.
+      // For devices that do not support the MayStart event type, this event can
+      // be used to interrupt ongoing APZ animations.
+      PANGESTURE_START,
 
-    // Pan: The actual pan motion by mPanDisplacement.
-    PANGESTURE_PAN,
+      // Pan: The actual pan motion by mPanDisplacement.
+      PANGESTURE_PAN,
 
-    // End: The pan gesture has ended, for example because the user has lifted
-    // their fingers from a touchpad after scrolling.
-    // Any potential momentum events fire after this event.
-    PANGESTURE_END,
+      // End: The pan gesture has ended, for example because the user has lifted
+      // their fingers from a touchpad after scrolling.
+      // Any potential momentum events fire after this event.
+      PANGESTURE_END,
 
-    // The following momentum event types are used in order to control the pan
-    // momentum animation. Using these instead of our own animation ensures
-    // that the animation curve is OS native and that the animation stops
-    // reliably if it is cancelled by the user.
+      // The following momentum event types are used in order to control the pan
+      // momentum animation. Using these instead of our own animation ensures
+      // that the animation curve is OS native and that the animation stops
+      // reliably if it is cancelled by the user.
 
-    // MomentumStart: Dispatched between the End event of the actual
-    // user-controlled pan, and the first MomentumPan event of the momentum
-    // animation.
-    PANGESTURE_MOMENTUMSTART,
-
-    // MomentumPan: The actual momentum motion by mPanDisplacement.
-    PANGESTURE_MOMENTUMPAN,
+      // MomentumStart: Dispatched between the End event of the actual
+      // user-controlled pan, and the first MomentumPan event of the momentum
+      // animation.
+      PANGESTURE_MOMENTUMSTART,
 
-    // MomentumEnd: The momentum animation has ended, for example because the
-    // momentum velocity has gone below the stopping threshold, or because the
-    // user has stopped the animation by putting their fingers on a touchpad.
-    PANGESTURE_MOMENTUMEND,
+      // MomentumPan: The actual momentum motion by mPanDisplacement.
+      PANGESTURE_MOMENTUMPAN,
 
-    // Used as an upper bound for ContiguousEnumSerializer
-    PANGESTURE_SENTINEL,
-  };
+      // MomentumEnd: The momentum animation has ended, for example because the
+      // momentum velocity has gone below the stopping threshold, or because the
+      // user has stopped the animation by putting their fingers on a touchpad.
+      PANGESTURE_MOMENTUMEND
+  ));
 
   PanGestureInput(PanGestureType aType,
                   uint32_t aTime,
                   TimeStamp aTimeStamp,
                   const ScreenPoint& aPanStartPoint,
                   const ScreenPoint& aPanDisplacement,
                   Modifiers aModifiers);
 
@@ -420,27 +396,22 @@ class PinchGestureInput : public InputDa
 {
 protected:
   friend mozilla::layers::PAPZCTreeManagerParent;
   friend mozilla::layers::APZCTreeManagerChild;
 
   PinchGestureInput();
 
 public:
-  enum PinchGestureType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-    PINCHGESTURE_START,
-    PINCHGESTURE_SCALE,
-    PINCHGESTURE_END,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    PINCHGESTURE_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    PinchGestureType, (
+      PINCHGESTURE_START,
+      PINCHGESTURE_SCALE,
+      PINCHGESTURE_END
+  ));
 
   // Construct a pinch gesture from a ParentLayer point.
   // mFocusPoint remains (0,0) unless it's set later.
   PinchGestureInput(PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
                     const ParentLayerPoint& aLocalFocusPoint,
                     ParentLayerCoord aCurrentSpan,
                     ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
 
@@ -482,31 +453,26 @@ class TapGestureInput : public InputData
 {
 protected:
   friend mozilla::layers::PAPZCTreeManagerParent;
   friend mozilla::layers::APZCTreeManagerChild;
 
   TapGestureInput();
 
 public:
-  enum TapGestureType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-    TAPGESTURE_LONG,
-    TAPGESTURE_LONG_UP,
-    TAPGESTURE_UP,
-    TAPGESTURE_CONFIRMED,
-    TAPGESTURE_DOUBLE,
-    TAPGESTURE_SECOND, // See GeckoContentController::TapType::eSecondTap
-    TAPGESTURE_CANCEL,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    TAPGESTURE_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    TapGestureType, (
+      TAPGESTURE_LONG,
+      TAPGESTURE_LONG_UP,
+      TAPGESTURE_UP,
+      TAPGESTURE_CONFIRMED,
+      TAPGESTURE_DOUBLE,
+      TAPGESTURE_SECOND, // See GeckoContentController::TapType::eSecondTap
+      TAPGESTURE_CANCEL
+  ));
 
   // Construct a tap gesture from a Screen point.
   // mLocalPoint remains (0,0) unless it's set later.
   TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
                   const ScreenIntPoint& aPoint, Modifiers aModifiers);
 
   // Construct a tap gesture from a ParentLayer point.
   // mPoint remains (0,0) unless it's set later.
@@ -534,42 +500,31 @@ class ScrollWheelInput : public InputDat
 {
 protected:
   friend mozilla::layers::PAPZCTreeManagerParent;
   friend mozilla::layers::APZCTreeManagerChild;
 
   ScrollWheelInput();
 
 public:
-  enum ScrollDeltaType
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-
-    // There are three kinds of scroll delta modes in Gecko: "page", "line" and
-    // "pixel".
-    SCROLLDELTA_LINE,
-    SCROLLDELTA_PAGE,
-    SCROLLDELTA_PIXEL,
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    ScrollDeltaType, (
+      // There are three kinds of scroll delta modes in Gecko: "page", "line" and
+      // "pixel".
+      SCROLLDELTA_LINE,
+      SCROLLDELTA_PAGE,
+      SCROLLDELTA_PIXEL
+  ));
 
-    // Used as an upper bound for ContiguousEnumSerializer
-    SCROLLDELTA_SENTINEL,
-  };
-
-  enum ScrollMode
-  {
-    // Warning, this enum is serialized and sent over IPC. If you reorder, add,
-    // or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
-
-    SCROLLMODE_INSTANT,
-    SCROLLMODE_SMOOTH,
-
-    // Used as an upper bound for ContiguousEnumSerializer
-    SCROLLMODE_SENTINEL,
-  };
+  MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
+    ScrollMode, (
+      SCROLLMODE_INSTANT,
+      SCROLLMODE_SMOOTH
+    )
+  );
 
   ScrollWheelInput(uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers,
                    ScrollMode aScrollMode, ScrollDeltaType aDeltaType,
                    const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY,
                    bool aAllowToOverrideSystemScrollSpeed);
   explicit ScrollWheelInput(const WidgetWheelEvent& aEvent);
 
   static ScrollDeltaType DeltaTypeForDeltaMode(uint32_t aDeltaMode);
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -1059,20 +1059,20 @@ struct ParamTraits<mozilla::widget::Cand
            ReadParam(aMsg, aIter, &aResult->mExcludeRect);
   }
 };
 
 // InputData.h
 
 template<>
 struct ParamTraits<mozilla::InputType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::InputType,
              mozilla::InputType::MULTITOUCH_INPUT,
-             mozilla::InputType::SENTINEL_INPUT>
+             mozilla::kHighestInputType>
 {};
 
 template<>
 struct ParamTraits<mozilla::InputData>
 {
   typedef mozilla::InputData paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1117,20 +1117,20 @@ struct ParamTraits<mozilla::SingleTouchD
             ReadParam(aMsg, aIter, &aResult->mRadius) &&
             ReadParam(aMsg, aIter, &aResult->mRotationAngle) &&
             ReadParam(aMsg, aIter, &aResult->mForce));
   }
 };
 
 template<>
 struct ParamTraits<mozilla::MultiTouchInput::MultiTouchType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::MultiTouchInput::MultiTouchType,
              mozilla::MultiTouchInput::MultiTouchType::MULTITOUCH_START,
-             mozilla::MultiTouchInput::MultiTouchType::MULTITOUCH_SENTINEL>
+             mozilla::MultiTouchInput::sHighestMultiTouchType>
 {};
 
 template<>
 struct ParamTraits<mozilla::MultiTouchInput>
 {
   typedef mozilla::MultiTouchInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1147,28 +1147,28 @@ struct ParamTraits<mozilla::MultiTouchIn
            ReadParam(aMsg, aIter, &aResult->mType) &&
            ReadParam(aMsg, aIter, &aResult->mTouches) &&
            ReadParam(aMsg, aIter, &aResult->mHandledByAPZ);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::MouseInput::MouseType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::MouseInput::MouseType,
              mozilla::MouseInput::MouseType::MOUSE_NONE,
-             mozilla::MouseInput::MouseType::MOUSE_SENTINEL>
+             mozilla::MouseInput::sHighestMouseType>
 {};
 
 template<>
 struct ParamTraits<mozilla::MouseInput::ButtonType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::MouseInput::ButtonType,
              mozilla::MouseInput::ButtonType::LEFT_BUTTON,
-             mozilla::MouseInput::ButtonType::BUTTON_SENTINEL>
+             mozilla::MouseInput::sHighestButtonType>
 {};
 
 template<>
 struct ParamTraits<mozilla::MouseInput>
 {
   typedef mozilla::MouseInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1193,20 +1193,20 @@ struct ParamTraits<mozilla::MouseInput>
            ReadParam(aMsg, aIter, &aResult->mOrigin) &&
            ReadParam(aMsg, aIter, &aResult->mLocalOrigin) &&
            ReadParam(aMsg, aIter, &aResult->mHandledByAPZ);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::PanGestureInput::PanGestureType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::PanGestureInput::PanGestureType,
              mozilla::PanGestureInput::PanGestureType::PANGESTURE_MAYSTART,
-             mozilla::PanGestureInput::PanGestureType::PANGESTURE_SENTINEL>
+             mozilla::PanGestureInput::sHighestPanGestureType>
 {};
 
 template<>
 struct ParamTraits<mozilla::PanGestureInput>
 {
   typedef mozilla::PanGestureInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1241,20 +1241,20 @@ struct ParamTraits<mozilla::PanGestureIn
            ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
            ReadParam(aMsg, aIter, &aResult->mFollowedByMomentum) &&
            ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::PinchGestureInput::PinchGestureType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::PinchGestureInput::PinchGestureType,
              mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_START,
-             mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_SENTINEL>
+             mozilla::PinchGestureInput::sHighestPinchGestureType>
 {};
 
 template<>
 struct ParamTraits<mozilla::PinchGestureInput>
 {
   typedef mozilla::PinchGestureInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1275,20 +1275,20 @@ struct ParamTraits<mozilla::PinchGesture
            ReadParam(aMsg, aIter, &aResult->mLocalFocusPoint) &&
            ReadParam(aMsg, aIter, &aResult->mCurrentSpan) &&
            ReadParam(aMsg, aIter, &aResult->mPreviousSpan);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::TapGestureInput::TapGestureType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::TapGestureInput::TapGestureType,
              mozilla::TapGestureInput::TapGestureType::TAPGESTURE_LONG,
-             mozilla::TapGestureInput::TapGestureType::TAPGESTURE_SENTINEL>
+             mozilla::TapGestureInput::sHighestTapGestureType>
 {};
 
 template<>
 struct ParamTraits<mozilla::TapGestureInput>
 {
   typedef mozilla::TapGestureInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
@@ -1305,28 +1305,28 @@ struct ParamTraits<mozilla::TapGestureIn
            ReadParam(aMsg, aIter, &aResult->mType) &&
            ReadParam(aMsg, aIter, &aResult->mPoint) &&
            ReadParam(aMsg, aIter, &aResult->mLocalPoint);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::ScrollWheelInput::ScrollDeltaType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::ScrollWheelInput::ScrollDeltaType,
              mozilla::ScrollWheelInput::ScrollDeltaType::SCROLLDELTA_LINE,
-             mozilla::ScrollWheelInput::ScrollDeltaType::SCROLLDELTA_SENTINEL>
+             mozilla::ScrollWheelInput::sHighestScrollDeltaType>
 {};
 
 template<>
 struct ParamTraits<mozilla::ScrollWheelInput::ScrollMode>
-  : public ContiguousEnumSerializer<
+  : public ContiguousEnumSerializerInclusive<
              mozilla::ScrollWheelInput::ScrollMode,
              mozilla::ScrollWheelInput::ScrollMode::SCROLLMODE_INSTANT,
-             mozilla::ScrollWheelInput::ScrollMode::SCROLLMODE_SENTINEL>
+             mozilla::ScrollWheelInput::sHighestScrollMode>
 {};
 
 template<>
 struct ParamTraits<mozilla::ScrollWheelInput>
 {
   typedef mozilla::ScrollWheelInput paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)