Bug 1377020 - Use MOZ_DEFINE_ENUM instead of a sentinel enumerator for enumerations in gfx/layers. r=kats draft
authorBotond Ballo <botond@mozilla.com>
Fri, 30 Jun 2017 21:18:55 -0400
changeset 604370 50d05ab09a5fb03d16c044edd38f0f3e0dba7ada
parent 604369 30f567edc6c6bb75971d27226ebfc3574944a9bb
child 636171 66d1edeb732c3b80c62ac45586d905e7c9c5a324
push id67049
push userbballo@mozilla.com
push dateWed, 05 Jul 2017 20:44:00 +0000
reviewerskats
bugs1377020
milestone56.0a1
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
@@ -1060,20 +1060,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)
@@ -1118,20 +1118,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)
@@ -1148,28 +1148,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)
@@ -1194,20 +1194,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)
@@ -1242,20 +1242,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)
@@ -1276,20 +1276,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)
@@ -1306,28 +1306,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)