ModifierKey unifies sk_app::Window::ModifierKey & Sample::Click::ModifierKey

Change-Id: Idb5dfe57a7f6e3d6078ab1e68d542b084114cfbe
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/225735
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/example/HelloWorld.cpp b/example/HelloWorld.cpp
index 9fff44e..be61f4f 100644
--- a/example/HelloWorld.cpp
+++ b/example/HelloWorld.cpp
@@ -109,7 +109,7 @@
     fWindow->inval();
 }
 
-bool HelloWorld::onChar(SkUnichar c, uint32_t modifiers) {
+bool HelloWorld::onChar(SkUnichar c, ModifierKey modifiers) {
     if (' ' == c) {
         fBackendType = Window::kRaster_BackendType == fBackendType ? Window::kNativeGL_BackendType
                                                                    : Window::kRaster_BackendType;
diff --git a/example/HelloWorld.h b/example/HelloWorld.h
index 56b0fe7..d88822e 100644
--- a/example/HelloWorld.h
+++ b/example/HelloWorld.h
@@ -22,7 +22,7 @@
 
     void onBackendCreated() override;
     void onPaint(SkSurface*) override;
-    bool onChar(SkUnichar c, uint32_t modifiers) override;
+    bool onChar(SkUnichar c, ModifierKey modifiers) override;
 
 private:
     void updateTitle();
diff --git a/experimental/editor/editor_application.cpp b/experimental/editor/editor_application.cpp
index 33395f5..0577d6a 100644
--- a/experimental/editor/editor_application.cpp
+++ b/experimental/editor/editor_application.cpp
@@ -8,6 +8,7 @@
 #include "include/core/SkSurface.h"
 #include "include/core/SkTime.h"
 
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/Application.h"
 #include "tools/sk_app/Window.h"
 
@@ -30,15 +31,15 @@
     }
 }
 
-static SkString modifiers_desc(uint32_t m) {
+static SkString modifiers_desc(ModifierKey m) {
     SkString s;
-    #define M(X) if (m & sk_app::Window::k ## X ##_ModifierKey) { s.append(" {" #X "}"); }
+    #define M(X) if (m & ModifierKey::k ## X ##) { s.append(" {" #X "}"); }
     M(Shift) M(Control) M(Option) M(Command) M(FirstPress)
     #undef M
     return s;
 }
 
-static void debug_on_char(SkUnichar c, uint32_t modifiers) {
+static void debug_on_char(SkUnichar c, ModifierKey modifiers) {
     SkString m = modifiers_desc(modifiers);
     if ((unsigned)c < 0x100) {
         SkDebugf("char: %c (0x%02X)%s\n", (char)(c & 0xFF), (unsigned)c, m.c_str());
@@ -47,8 +48,8 @@
     }
 }
 
-static void debug_on_key(sk_app::Window::Key key, sk_app::Window::InputState, uint32_t modifiers) {
-    SkDebugf("key: %s%s\n", key_name(key), modifiers_desc(modifiers).c_str());
+static void debug_on_key(sk_app::Window::Key key, sk_app::Window::InputState, ModifierKey modi) {
+    SkDebugf("key: %s%s\n", key_name(key), modifiers_desc(modi).c_str());
 }
 #endif  // SK_EDITOR_DEBUG_OUT
 
@@ -146,12 +147,12 @@
 
     void inval() { if (fParent) { fParent->inval(); } }
 
-    bool onMouseWheel(float delta, uint32_t modifiers) override {
+    bool onMouseWheel(float delta, ModifierKey modifiers) override {
         this->scroll(-(int)(delta * fEditor.font().getSpacing()));
         return true;
     }
 
-    bool onMouse(int x, int y, sk_app::Window::InputState state, uint32_t modifiers) override {
+    bool onMouse(int x, int y, sk_app::Window::InputState state, ModifierKey modifiers) override {
         if (sk_app::Window::kDown_InputState == state) {
             y += fPos;
             editor::Editor::TextPosition pos = fEditor.getPosition(SkIPoint{x, y});
@@ -166,10 +167,10 @@
         return true;
     }
 
-    bool onChar(SkUnichar c, uint32_t modifiers) override {
-        if (0 == (modifiers & (sk_app::Window::kControl_ModifierKey |
-                               sk_app::Window::kOption_ModifierKey |
-                               sk_app::Window::kCommand_ModifierKey))) {
+    bool onChar(SkUnichar c, ModifierKey modifiers) override {
+        if (!ModifierKeyIsSet(modifiers & (ModifierKey::kControl |
+                                           ModifierKey::kOption  |
+                                           ModifierKey::kCommand))) {
             if (((unsigned)c < 0x7F && (unsigned)c >= 0x20) || c == '\n') {
                 char ch = (char)c;
                 fEditor.insert(fTextPos, &ch, 1);
@@ -179,7 +180,7 @@
                 return this->moveCursor(editor::Editor::Movement::kRight);
             }
         }
-        if (modifiers == sk_app::Window::kControl_ModifierKey) {
+        if (modifiers == ModifierKey::kControl) {
             switch (c) {
                 case 'p':
                     for (const editor::StringSlice& str : fEditor.text()) {
@@ -232,7 +233,7 @@
     }
     bool onKey(sk_app::Window::Key key,
                sk_app::Window::InputState state,
-               uint32_t modifiers) override {
+               ModifierKey modifiers) override {
         if (state == sk_app::Window::kDown_InputState) {
             switch (key) {
                 case sk_app::Window::Key::kPageDown:
@@ -246,7 +247,7 @@
                 case sk_app::Window::Key::kHome:
                 case sk_app::Window::Key::kEnd:
                     return this->moveCursor(convert(key),
-                                            modifiers & sk_app::Window::kShift_ModifierKey);
+                                            (int)(modifiers & ModifierKey::kShift));
                 case sk_app::Window::Key::kDelete:
                     if (fMarkPos != editor::Editor::TextPosition()) {
                         fTextPos = fEditor.remove(fMarkPos, fTextPos);
diff --git a/samplecode/PerlinPatch.cpp b/samplecode/PerlinPatch.cpp
index 2e404ad..49a55ea 100644
--- a/samplecode/PerlinPatch.cpp
+++ b/samplecode/PerlinPatch.cpp
@@ -10,6 +10,7 @@
 #include "include/effects/SkPerlinNoiseShader.h"
 #include "samplecode/Sample.h"
 #include "src/utils/SkPatchUtils.h"
+#include "tools/ModifierKey.h"
 #include "tools/timer/AnimTimer.h"
 
 static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
@@ -167,13 +168,11 @@
         return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
-        // holding down shift
-        if (1 == modi) {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
+        if (ModifierKey::kShift == modi) {
             return new PtClick(this, -1);
         }
-        // holding down ctrl
-        if (2 == modi) {
+        if (ModifierKey::kControl == modi) {
             return new PtClick(this, -2);
         }
         SkPoint clickPoint = {x, y};
diff --git a/samplecode/Sample.cpp b/samplecode/Sample.cpp
index 9ee3b84..67d9da0 100644
--- a/samplecode/Sample.cpp
+++ b/samplecode/Sample.cpp
@@ -68,7 +68,7 @@
 
 Sample::Click::~Click() {}
 
-Sample::Click* Sample::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
+Sample::Click* Sample::findClickHandler(SkScalar x, SkScalar y, ModifierKey modi) {
     if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
         return nullptr;
     }
@@ -76,7 +76,7 @@
     return this->onFindClickHandler(x, y, modi);
 }
 
-void Sample::DoClickDown(Click* click, int x, int y, unsigned modi) {
+void Sample::DoClickDown(Click* click, int x, int y, ModifierKey modi) {
     SkASSERT(click);
 
     Sample* target = click->fTarget.get();
@@ -95,7 +95,7 @@
     target->onClick(click);
 }
 
-void Sample::DoClickMoved(Click* click, int x, int y, unsigned modi) {
+void Sample::DoClickMoved(Click* click, int x, int y, ModifierKey modi) {
     SkASSERT(click);
 
     Sample* target = click->fTarget.get();
@@ -114,7 +114,7 @@
     target->onClick(click);
 }
 
-void Sample::DoClickUp(Click* click, int x, int y, unsigned modi) {
+void Sample::DoClickUp(Click* click, int x, int y, ModifierKey modi) {
     SkASSERT(click);
 
     Sample* target = click->fTarget.get();
@@ -137,7 +137,7 @@
 
 void Sample::onSizeChange() {}
 
-Sample::Click* Sample::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
+Sample::Click* Sample::onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) {
     return nullptr;
 }
 
diff --git a/samplecode/Sample.h b/samplecode/Sample.h
index 0d538d2..7b511c5 100644
--- a/samplecode/Sample.h
+++ b/samplecode/Sample.h
@@ -14,6 +14,7 @@
 #include "include/core/SkString.h"
 #include "include/private/SkMacros.h"
 #include "src/utils/SkMetaData.h"
+#include "tools/ModifierKey.h"
 #include "tools/Registry.h"
 
 class AnimTimer;
@@ -60,16 +61,10 @@
             kMoved_State,
             kUp_State
         };
-        enum ModifierKeys {
-            kShift_ModifierKey    = 1 << 0,
-            kControl_ModifierKey  = 1 << 1,
-            kOption_ModifierKey   = 1 << 2,   // same as ALT
-            kCommand_ModifierKey  = 1 << 3,
-        };
         SkPoint     fOrig, fPrev, fCurr;
         SkIPoint    fIOrig, fIPrev, fICurr;
         State       fState;
-        unsigned    fModifierKeys;
+        ModifierKey fModifierKeys = ModifierKey::kNone;
 
         SkMetaData  fMeta;
     private:
@@ -77,10 +72,10 @@
 
         friend class Sample;
     };
-    Click* findClickHandler(SkScalar x, SkScalar y, unsigned modifierKeys);
-    static void DoClickDown(Click*, int x, int y, unsigned modi);
-    static void DoClickMoved(Click*, int x, int y, unsigned modi);
-    static void DoClickUp(Click*, int x, int y, unsigned modi);
+    Click* findClickHandler(SkScalar x, SkScalar y, ModifierKey modifierKeys);
+    static void DoClickDown(Click*, int x, int y, ModifierKey modi);
+    static void DoClickMoved(Click*, int x, int y, ModifierKey modi);
+    static void DoClickUp(Click*, int x, int y, ModifierKey modi);
 
     void setBGColor(SkColor color) { fBGColor = color; }
     bool animate(const AnimTimer& timer) { return this->onAnimate(timer); }
@@ -92,7 +87,7 @@
     virtual void onSizeChange();
 
     /** Override this if you might handle the click */
-    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi);
+    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi);
 
     /** Override to track clicks. Return true as long as you want to track the pen/mouse. */
     virtual bool onClick(Click*);
diff --git a/samplecode/SampleAAGeometry.cpp b/samplecode/SampleAAGeometry.cpp
index 515f4f7..c3c0f8d 100644
--- a/samplecode/SampleAAGeometry.cpp
+++ b/samplecode/SampleAAGeometry.cpp
@@ -1611,7 +1611,7 @@
         return -1;
     }
 
-    virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         SkPoint pt = {x, y};
         int ptHit = hittest_pt(pt);
         if (ptHit >= 0) {
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index dd9d298..6908e98 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -48,7 +48,7 @@
     CCPRGeometryView() { this->updateGpuData(); }
     void onDrawContent(SkCanvas*) override;
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override;
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override;
     bool onClick(Sample::Click*) override;
     bool onChar(SkUnichar) override;
     SkString name() override { return SkString("CCPRGeometry"); }
@@ -422,7 +422,7 @@
     int fPtIdx;
 };
 
-Sample::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsigned) {
+Sample::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) {
     for (int i = 0; i < 4; ++i) {
         if (PrimitiveType::kCubics != fPrimitiveType && 2 == i) {
             continue;
diff --git a/samplecode/SampleDegenerateQuads.cpp b/samplecode/SampleDegenerateQuads.cpp
index 895a6d2..5303594 100644
--- a/samplecode/SampleDegenerateQuads.cpp
+++ b/samplecode/SampleDegenerateQuads.cpp
@@ -380,8 +380,7 @@
         }
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
-                                      unsigned) override;
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override;
     bool onClick(Sample::Click*) override;
     bool onChar(SkUnichar) override;
     SkString name() override { return SkString("DegenerateQuad"); }
@@ -480,7 +479,7 @@
     }
 };
 
-Sample::Click* DegenerateQuadSample::onFindClickHandler(SkScalar x, SkScalar y, unsigned) {
+Sample::Click* DegenerateQuadSample::onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) {
     SkPoint inCTM = SkPoint::Make((x - kViewOffset) / kViewScale, (y - kViewOffset) / kViewScale);
     for (int i = 0; i < 4; ++i) {
         if ((fCorners[i] - inCTM).length() < 10.f / kViewScale) {
diff --git a/samplecode/SampleFatBits.cpp b/samplecode/SampleFatBits.cpp
index 0eaec1d..d661aaa 100644
--- a/samplecode/SampleFatBits.cpp
+++ b/samplecode/SampleFatBits.cpp
@@ -468,7 +468,7 @@
         }
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         SkPoint pt = { x, y };
         int index = -1;
         int count = fFB.getTriangle() ? 3 : 2;
diff --git a/samplecode/SampleHT.cpp b/samplecode/SampleHT.cpp
index e225193..7483b80 100644
--- a/samplecode/SampleHT.cpp
+++ b/samplecode/SampleHT.cpp
@@ -156,7 +156,7 @@
         return true;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         // search backwards to find the top-most
         for (int i = N - 1; i >= 0; --i) {
             if (fArray[i].fDrawable->hitTest(x, y)) {
diff --git a/samplecode/SampleHairline.cpp b/samplecode/SampleHairline.cpp
index af4244a..aafa564 100644
--- a/samplecode/SampleHairline.cpp
+++ b/samplecode/SampleHairline.cpp
@@ -217,7 +217,7 @@
         return true;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         fDoAA = !fDoAA;
         return this->INHERITED::onFindClickHandler(x, y, modi);
     }
diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp
index 03388e6..cb981f5 100644
--- a/samplecode/SampleLayers.cpp
+++ b/samplecode/SampleLayers.cpp
@@ -224,7 +224,7 @@
         return true;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         return new Click(this);
     }
 
diff --git a/samplecode/SampleLighting.cpp b/samplecode/SampleLighting.cpp
index 68bc53f..022e44d 100644
--- a/samplecode/SampleLighting.cpp
+++ b/samplecode/SampleLighting.cpp
@@ -65,7 +65,7 @@
         canvas->drawRect(fRect, paint);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         return this->INHERITED::onFindClickHandler(x, y, modi);
     }
 
diff --git a/samplecode/SampleLua.cpp b/samplecode/SampleLua.cpp
index 469d0a6..9416248 100644
--- a/samplecode/SampleLua.cpp
+++ b/samplecode/SampleLua.cpp
@@ -109,7 +109,7 @@
     }
 
     virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
-                                              unsigned modi) override {
+                                              ModifierKey modi) override {
         lua_State* L = this->ensureLua();
         lua_getglobal(L, gClickName);
         if (lua_isfunction(L, -1)) {
diff --git a/samplecode/SampleMixer.cpp b/samplecode/SampleMixer.cpp
index 34cc8d6..1def7db 100644
--- a/samplecode/SampleMixer.cpp
+++ b/samplecode/SampleMixer.cpp
@@ -71,7 +71,7 @@
         }
     }
 
-    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         return fRect.contains(SkScalarRoundToInt(x),
                               SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
     }
@@ -154,7 +154,7 @@
         canvas->restore();
     }
 
-    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         fMode = (fMode == SkBlendMode::kSrcOver) ? SkBlendMode::kClear : SkBlendMode::kSrcOver;
         return fRect.contains(SkScalarRoundToInt(x),
                               SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
diff --git a/samplecode/SamplePatch.cpp b/samplecode/SamplePatch.cpp
index 71c88d9..a970400 100644
--- a/samplecode/SamplePatch.cpp
+++ b/samplecode/SamplePatch.cpp
@@ -297,7 +297,7 @@
         return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         x -= DX;
         y -= DY;
         for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
@@ -396,7 +396,7 @@
  //       canvas->drawPath(fPath, fSkeletonP);
     }
 
-    Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         Click* click = new Click(this);
         fPath.reset();
         fPath.moveTo(x, y);
@@ -484,7 +484,7 @@
         this->dodraw(canvas, nullptr, 600, 0, &p);
     }
 
-    Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         Click* click = new Click(this);
         fPath.reset();
         fPath.moveTo(x, y);
diff --git a/samplecode/SamplePath.cpp b/samplecode/SamplePath.cpp
index bdb51ab..de52fa8 100644
--- a/samplecode/SamplePath.cpp
+++ b/samplecode/SamplePath.cpp
@@ -189,7 +189,7 @@
         return true;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         fShowHairline = !fShowHairline;
         return this->INHERITED::onFindClickHandler(x, y, modi);
     }
@@ -289,7 +289,7 @@
         return false;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         const SkScalar tol = 4;
         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
         for (int i = 0; i < N; ++i) {
@@ -417,7 +417,7 @@
         return false;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         const SkScalar tol = 4;
         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
         for (int i = 0; i < N; ++i) {
@@ -534,7 +534,7 @@
         return false;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         const SkScalar tol = 8;
         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
         for (int i = 0; i < N; ++i) {
@@ -730,7 +730,7 @@
         return false;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         const SkScalar tol = 8;
         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
         for (int i = 0; i < N; ++i) {
diff --git a/samplecode/SamplePathClip.cpp b/samplecode/SamplePathClip.cpp
index f5ef4c5..5760d68 100644
--- a/samplecode/SamplePathClip.cpp
+++ b/samplecode/SamplePathClip.cpp
@@ -52,7 +52,7 @@
         canvas->drawOval(oval, p);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         return new Click(this);
     }
 
@@ -278,7 +278,7 @@
         return dx*dx + dy*dy <= rad*rad;
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         for (int i = 0; i < N; ++i) {
             if (hit_test(fPoly[i], x, y)) {
                 return new VertClick(this, &fPoly[i]);
diff --git a/samplecode/SampleQuadStroker.cpp b/samplecode/SampleQuadStroker.cpp
index 4de89e2..13cd306 100644
--- a/samplecode/SampleQuadStroker.cpp
+++ b/samplecode/SampleQuadStroker.cpp
@@ -722,7 +722,7 @@
     };
 
     virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
-                                              unsigned modi) override {
+                                              ModifierKey modi) override {
         for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) {
             if (hittest(fPts[i], x, y)) {
                 return new MyClick(this, (int)i);
diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp
index a160549..cff677f 100644
--- a/samplecode/SampleRegion.cpp
+++ b/samplecode/SampleRegion.cpp
@@ -326,7 +326,7 @@
     }
 
     virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
-                                              unsigned modi) override {
+                                              ModifierKey modi) override {
         return fRect.contains(SkScalarRoundToInt(x),
                               SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
     }
diff --git a/samplecode/SampleSG.cpp b/samplecode/SampleSG.cpp
index fc29c39..e129de1 100644
--- a/samplecode/SampleSG.cpp
+++ b/samplecode/SampleSG.cpp
@@ -72,7 +72,7 @@
         fScene->render(canvas);
     }
 
-    Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+    Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
         if (auto node = fScene->nodeAt({x, y})) {
             Click* click = new Click(this);
             click->fMeta.setPtr("node", (void*)node);
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 346ba60..ed8bf7a 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -443,7 +443,7 @@
         gProc[fIndex](canvas);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         this->init();
         fIndex = (fIndex + 1) % SK_ARRAY_COUNT(gProc);
         return nullptr;
diff --git a/samplecode/SampleStringArt.cpp b/samplecode/SampleStringArt.cpp
index 50d2136..2eaf4e3 100644
--- a/samplecode/SampleStringArt.cpp
+++ b/samplecode/SampleStringArt.cpp
@@ -50,7 +50,7 @@
         canvas->drawPath(path, paint);
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         fAngle = x/width();
         return nullptr;
     }
diff --git a/samplecode/SampleVertices.cpp b/samplecode/SampleVertices.cpp
index 911418b..1db11c1 100644
--- a/samplecode/SampleVertices.cpp
+++ b/samplecode/SampleVertices.cpp
@@ -99,7 +99,7 @@
         }
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         return new Click(this);
     }
 
diff --git a/samplecode/SampleXfer.cpp b/samplecode/SampleXfer.cpp
index ccf9f87..6e607f6 100644
--- a/samplecode/SampleXfer.cpp
+++ b/samplecode/SampleXfer.cpp
@@ -161,7 +161,7 @@
         canvas->restore();
     }
 
-    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
+    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
         // Check mode buttons first
         for (int i = 0; i < N_Modes; ++i) {
             if (fModeButtons[i].hitTest(x, y)) {
diff --git a/tools/ModifierKey.h b/tools/ModifierKey.h
new file mode 100644
index 0000000..5f4d25d
--- /dev/null
+++ b/tools/ModifierKey.h
@@ -0,0 +1,25 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef ModifierKey_DEFINED
+#define ModifierKey_DEFINED
+
+#include "include/private/SkBitmaskEnum.h"
+
+enum class ModifierKey {
+    kNone       = 0,
+    kShift      = 1 << 0,
+    kControl    = 1 << 1,
+    kOption     = 1 << 2,   // same as ALT
+    kCommand    = 1 << 3,
+    kFirstPress = 1 << 4,
+};
+
+namespace skstd {
+template <> struct is_bitmask_enum<ModifierKey> : std::true_type {};
+}
+
+static inline bool ModifierKeyIsSet(ModifierKey m) {
+    return m != ModifierKey::kNone;
+}
+
+#endif  // ModifierKey_DEFINED
diff --git a/tools/sk_app/CommandSet.cpp b/tools/sk_app/CommandSet.cpp
index 984c8d9..b2bb2ad 100644
--- a/tools/sk_app/CommandSet.cpp
+++ b/tools/sk_app/CommandSet.cpp
@@ -35,7 +35,7 @@
     fWindow = window;
 }
 
-bool CommandSet::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) {
+bool CommandSet::onKey(Window::Key key, Window::InputState state, ModifierKey modifiers) {
     if (Window::kDown_InputState == state) {
         for (Command& cmd : fCommands) {
             if (Command::kKey_CommandType == cmd.fType && key == cmd.fKey) {
@@ -48,7 +48,7 @@
     return false;
 }
 
-bool CommandSet::onChar(SkUnichar c, uint32_t modifiers) {
+bool CommandSet::onChar(SkUnichar c, ModifierKey modifiers) {
     for (Command& cmd : fCommands) {
         if (Command::kChar_CommandType == cmd.fType && c == cmd.fChar) {
             cmd.fFunction();
diff --git a/tools/sk_app/CommandSet.h b/tools/sk_app/CommandSet.h
index f3e29e7..7e99e3c 100644
--- a/tools/sk_app/CommandSet.h
+++ b/tools/sk_app/CommandSet.h
@@ -41,8 +41,8 @@
     CommandSet();
 
     void attach(Window* window);
-    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
-    bool onChar(SkUnichar, uint32_t modifiers);
+    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, ModifierKey modifiers);
+    bool onChar(SkUnichar, ModifierKey modifiers);
     bool onSoftkey(const SkString& softkey);
 
     void addCommand(SkUnichar c, const char* group, const char* description,
diff --git a/tools/sk_app/Window.cpp b/tools/sk_app/Window.cpp
index a259d76..a873158 100644
--- a/tools/sk_app/Window.cpp
+++ b/tools/sk_app/Window.cpp
@@ -41,19 +41,19 @@
     this->visitLayers([](Layer* layer) { layer->onBackendCreated(); });
 }
 
-bool Window::onChar(SkUnichar c, uint32_t modifiers) {
+bool Window::onChar(SkUnichar c, ModifierKey modifiers) {
     return this->signalLayers([=](Layer* layer) { return layer->onChar(c, modifiers); });
 }
 
-bool Window::onKey(Key key, InputState state, uint32_t modifiers) {
+bool Window::onKey(Key key, InputState state, ModifierKey modifiers) {
     return this->signalLayers([=](Layer* layer) { return layer->onKey(key, state, modifiers); });
 }
 
-bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
+bool Window::onMouse(int x, int y, InputState state, ModifierKey modifiers) {
     return this->signalLayers([=](Layer* layer) { return layer->onMouse(x, y, state, modifiers); });
 }
 
-bool Window::onMouseWheel(float delta, uint32_t modifiers) {
+bool Window::onMouseWheel(float delta, ModifierKey modifiers) {
     return this->signalLayers([=](Layer* layer) { return layer->onMouseWheel(delta, modifiers); });
 }
 
diff --git a/tools/sk_app/Window.h b/tools/sk_app/Window.h
index ef8bf73..81b13f9 100644
--- a/tools/sk_app/Window.h
+++ b/tools/sk_app/Window.h
@@ -11,6 +11,7 @@
 #include "include/core/SkRect.h"
 #include "include/core/SkTypes.h"
 #include "include/private/SkTDArray.h"
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/DisplayParams.h"
 
 class GrContext;
@@ -120,14 +121,6 @@
     };
     static const int kKeyCount = static_cast<int>(Key::kLast) + 1;
 
-    enum ModifierKeys {
-        kShift_ModifierKey = 1 << 0,
-        kControl_ModifierKey = 1 << 1,
-        kOption_ModifierKey = 1 << 2,   // same as ALT
-        kCommand_ModifierKey = 1 << 3,
-        kFirstPress_ModifierKey = 1 << 4,
-    };
-
     enum InputState {
         kDown_InputState,
         kUp_InputState,
@@ -145,10 +138,10 @@
         // return value of 'true' means 'I have handled this event'
         virtual void onBackendCreated() {}
         virtual void onAttach(Window* window) {}
-        virtual bool onChar(SkUnichar c, uint32_t modifiers) { return false; }
-        virtual bool onKey(Key key, InputState state, uint32_t modifiers) { return false; }
-        virtual bool onMouse(int x, int y, InputState state, uint32_t modifiers) { return false; }
-        virtual bool onMouseWheel(float delta, uint32_t modifiers) { return false; }
+        virtual bool onChar(SkUnichar c, ModifierKey modifiers) { return false; }
+        virtual bool onKey(Key key, InputState state, ModifierKey modifiers) { return false; }
+        virtual bool onMouse(int x, int y, InputState state, ModifierKey modifiers) { return false; }
+        virtual bool onMouseWheel(float delta, ModifierKey modifiers) { return false; }
         virtual bool onTouch(intptr_t owner, InputState state, float x, float y) { return false; }
         virtual void onUIStateChanged(const SkString& stateName, const SkString& stateValue) {}
         virtual void onPrePaint() {}
@@ -166,10 +159,10 @@
     }
 
     void onBackendCreated();
-    bool onChar(SkUnichar c, uint32_t modifiers);
-    bool onKey(Key key, InputState state, uint32_t modifiers);
-    bool onMouse(int x, int y, InputState state, uint32_t modifiers);
-    bool onMouseWheel(float delta, uint32_t modifiers);
+    bool onChar(SkUnichar c, ModifierKey modifiers);
+    bool onKey(Key key, InputState state, ModifierKey modifiers);
+    bool onMouse(int x, int y, InputState state, ModifierKey modifiers);
+    bool onMouseWheel(float delta, ModifierKey modifiers);
     bool onTouch(intptr_t owner, InputState state, float x, float y);  // multi-owner = multi-touch
     void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
     void onPaint();
diff --git a/tools/sk_app/android/surface_glue_android.cpp b/tools/sk_app/android/surface_glue_android.cpp
index 3ddb95e..690da75 100644
--- a/tools/sk_app/android/surface_glue_android.cpp
+++ b/tools/sk_app/android/surface_glue_android.cpp
@@ -166,8 +166,8 @@
             auto it = ANDROID_TO_WINDOW_KEYMAP.find(message.fKeycode);
             SkASSERT(it != ANDROID_TO_WINDOW_KEYMAP.end());
             // No modifier is supported so far
-            skiaAndroidApp->fWindow->onKey(it->second, Window::kDown_InputState, 0);
-            skiaAndroidApp->fWindow->onKey(it->second, Window::kUp_InputState, 0);
+            skiaAndroidApp->fWindow->onKey(it->second, Window::kDown_InputState, ModifierKey::kNone);
+            skiaAndroidApp->fWindow->onKey(it->second, Window::kUp_InputState, ModifierKey::kNone);
             break;
         }
         case kTouched: {
diff --git a/tools/sk_app/ios/Window_ios.cpp b/tools/sk_app/ios/Window_ios.cpp
index 21b510a..2eb683f 100644
--- a/tools/sk_app/ios/Window_ios.cpp
+++ b/tools/sk_app/ios/Window_ios.cpp
@@ -6,6 +6,7 @@
 */
 
 #include "src/core/SkUtils.h"
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/ios/WindowContextFactory_ios.h"
 #include "tools/sk_app/ios/Window_ios.h"
 #include "tools/timer/Timer.h"
@@ -135,17 +136,17 @@
     return Window::Key::kNONE;
 }
 
-static uint32_t get_modifiers(const SDL_Event& event) {
+static ModifierKey get_modifiers(const SDL_Event& event) {
     static const struct {
         unsigned    fSDLMask;
-        unsigned    fSkMask;
+        ModifierKey fSkMask;
     } gModifiers[] = {
-        { KMOD_SHIFT, Window::kShift_ModifierKey },
-        { KMOD_CTRL,  Window::kControl_ModifierKey },
-        { KMOD_ALT,   Window::kOption_ModifierKey },
+        { KMOD_SHIFT, ModifierKey::kShift },
+        { KMOD_CTRL,  ModifierKey::kControl },
+        { KMOD_ALT,   ModifierKey::kOption },
     };
 
-    auto modifiers = 0;
+    ModifierKey modifiers = ModifierKey::kNone;
 
     switch (event.type) {
         case SDL_KEYDOWN:
@@ -157,7 +158,7 @@
                 }
             }
             if (0 == event.key.repeat) {
-                modifiers |= Window::kFirstPress_ModifierKey;
+                modifiers |= ModifierKey::kFirstPress;
             }
             break;
         }
diff --git a/tools/sk_app/mac/Window_mac.mm b/tools/sk_app/mac/Window_mac.mm
index cc08c30..65069d8 100644
--- a/tools/sk_app/mac/Window_mac.mm
+++ b/tools/sk_app/mac/Window_mac.mm
@@ -6,6 +6,7 @@
 */
 
 #include "src/core/SkUtils.h"
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/mac/WindowContextFactory_mac.h"
 #include "tools/sk_app/mac/Window_mac.h"
 
@@ -228,23 +229,23 @@
     return Window::Key::kNONE;
 }
 
-static uint32_t get_modifiers(const NSEvent* event) {
+static ModifierKey get_modifiers(const NSEvent* event) {
     NSUInteger modifierFlags = [event modifierFlags];
-    auto modifiers = 0;
+    ModifierKey modifiers = ModifierKey::kNone;
 
     if (modifierFlags & NSEventModifierFlagShift) {
-        modifiers |= Window::kShift_ModifierKey;
+        modifiers |= ModifierKey::kShift;
     }
     if (modifierFlags & NSEventModifierFlagControl) {
-        modifiers |= Window::kControl_ModifierKey;
+        modifiers |= ModifierKey::kControl;
     }
     if (modifierFlags & NSEventModifierFlagOption) {
-        modifiers |= Window::kOption_ModifierKey;
+        modifiers |= ModifierKey::kOption;
     }
 
     if ((NSKeyDown == [event type] || NSKeyUp == [event type]) &&
         NO == [event isARepeat]) {
-        modifiers |= Window::kFirstPress_ModifierKey;
+        modifiers |= ModifierKey::kFirstPress;
     }
 
     return modifiers;
diff --git a/tools/sk_app/unix/Window_unix.cpp b/tools/sk_app/unix/Window_unix.cpp
index 2dbd680..6236193 100644
--- a/tools/sk_app/unix/Window_unix.cpp
+++ b/tools/sk_app/unix/Window_unix.cpp
@@ -2,6 +2,11 @@
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
+* f 49
+* Prev
+* Up
+*
+*
 * found in the LICENSE file.
 */
 
@@ -10,6 +15,7 @@
 #include "tools/sk_app/unix/WindowContextFactory_unix.h"
 
 #include "src/utils/SkUTF.h"
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/GLWindowContext.h"
 #include "tools/sk_app/unix/Window_unix.h"
 #include "tools/timer/Timer.h"
@@ -224,17 +230,17 @@
     return Window::Key::kNONE;
 }
 
-static uint32_t get_modifiers(const XEvent& event) {
+static ModifierKey get_modifiers(const XEvent& event) {
     static const struct {
         unsigned    fXMask;
-        unsigned    fSkMask;
+        ModifierKey  fSkMask;
     } gModifiers[] = {
-        { ShiftMask,   Window::kShift_ModifierKey },
-        { ControlMask, Window::kControl_ModifierKey },
-        { Mod1Mask,    Window::kOption_ModifierKey },
+        { ShiftMask,   ModifierKey::kShift },
+        { ControlMask, ModifierKey::kControl },
+        { Mod1Mask,    ModifierKey::kOption },
     };
 
-    auto modifiers = 0;
+    ModifierKey modifiers = ModifierKey::kNone;
     for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
         if (event.xkey.state & gModifiers[i].fXMask) {
             modifiers |= gModifiers[i].fSkMask;
diff --git a/tools/sk_app/win/Window_win.cpp b/tools/sk_app/win/Window_win.cpp
index 66ebc19..7a1af00 100644
--- a/tools/sk_app/win/Window_win.cpp
+++ b/tools/sk_app/win/Window_win.cpp
@@ -14,8 +14,10 @@
 #include <windowsx.h>
 
 #include "src/core/SkUtils.h"
+#include "tools/ModifierKey.h"
 #include "tools/sk_app/WindowContext.h"
 #include "tools/sk_app/win/WindowContextFactory_win.h"
+
 #ifdef SK_VULKAN
 #include "tools/sk_app/VulkanWindowContext.h"
 #endif
@@ -158,34 +160,34 @@
     return Window::Key::kNONE;
 }
 
-static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
-    uint32_t modifiers = 0;
+static ModifierKey get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
+    ModifierKey modifiers = ModifierKey::kNone;
 
     switch (message) {
         case WM_UNICHAR:
         case WM_CHAR:
             if (0 == (lParam & (1 << 30))) {
-                modifiers |= Window::kFirstPress_ModifierKey;
+                modifiers |= ModifierKey::kFirstPress;
             }
             if (lParam & (1 << 29)) {
-                modifiers |= Window::kOption_ModifierKey;
+                modifiers |= ModifierKey::kOption;
             }
             break;
 
         case WM_KEYDOWN:
         case WM_SYSKEYDOWN:
             if (0 == (lParam & (1 << 30))) {
-                modifiers |= Window::kFirstPress_ModifierKey;
+                modifiers |= ModifierKey::kFirstPress;
             }
             if (lParam & (1 << 29)) {
-                modifiers |= Window::kOption_ModifierKey;
+                modifiers |= ModifierKey::kOption;
             }
             break;
 
         case WM_KEYUP:
         case WM_SYSKEYUP:
             if (lParam & (1 << 29)) {
-                modifiers |= Window::kOption_ModifierKey;
+                modifiers |= ModifierKey::kOption;
             }
             break;
 
@@ -194,10 +196,10 @@
         case WM_MOUSEMOVE:
         case WM_MOUSEWHEEL:
             if (wParam & MK_CONTROL) {
-                modifiers |= Window::kControl_ModifierKey;
+                modifiers |= ModifierKey::kControl;
             }
             if (wParam & MK_SHIFT) {
-                modifiers |= Window::kShift_ModifierKey;
+                modifiers |= ModifierKey::kShift;
             }
             break;
     }
diff --git a/tools/viewer/ImGuiLayer.cpp b/tools/viewer/ImGuiLayer.cpp
index 6203375..790a040 100644
--- a/tools/viewer/ImGuiLayer.cpp
+++ b/tools/viewer/ImGuiLayer.cpp
@@ -70,7 +70,7 @@
     fWindow = window;
 }
 
-bool ImGuiLayer::onMouse(int x, int y, Window::InputState state, uint32_t modifiers) {
+bool ImGuiLayer::onMouse(int x, int y, Window::InputState state, ModifierKey modifiers) {
     ImGuiIO& io = ImGui::GetIO();
     io.MousePos.x = static_cast<float>(x);
     io.MousePos.y = static_cast<float>(y);
@@ -82,7 +82,7 @@
     return io.WantCaptureMouse;
 }
 
-bool ImGuiLayer::onMouseWheel(float delta, uint32_t modifiers) {
+bool ImGuiLayer::onMouseWheel(float delta, ModifierKey modifiers) {
     ImGuiIO& io = ImGui::GetIO();
     io.MouseWheel += delta;
     return true;
@@ -184,13 +184,13 @@
     fSkiaWidgetFuncs.reset();
 }
 
-bool ImGuiLayer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
+bool ImGuiLayer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, ModifierKey modifiers) {
     ImGuiIO& io = ImGui::GetIO();
     io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
     return io.WantCaptureKeyboard;
 }
 
-bool ImGuiLayer::onChar(SkUnichar c, uint32_t modifiers) {
+bool ImGuiLayer::onChar(SkUnichar c, ModifierKey modifiers) {
     ImGuiIO& io = ImGui::GetIO();
     if (io.WantTextInput) {
         if (c > 0 && c < 0x10000) {
diff --git a/tools/viewer/ImGuiLayer.h b/tools/viewer/ImGuiLayer.h
index 0f83514..dfd383b 100644
--- a/tools/viewer/ImGuiLayer.h
+++ b/tools/viewer/ImGuiLayer.h
@@ -123,10 +123,10 @@
     void onAttach(sk_app::Window* window) override;
     void onPrePaint() override;
     void onPaint(SkSurface*) override;
-    bool onMouse(int x, int y, sk_app::Window::InputState state, uint32_t modifiers) override;
-    bool onMouseWheel(float delta, uint32_t modifiers) override;
-    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) override;
-    bool onChar(SkUnichar c, uint32_t modifiers) override;
+    bool onMouse(int x, int y, sk_app::Window::InputState state, ModifierKey modifiers) override;
+    bool onMouseWheel(float delta, ModifierKey modifiers) override;
+    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, ModifierKey modifiers) override;
+    bool onChar(SkUnichar c, ModifierKey modifiers) override;
 
 private:
     sk_app::Window* fWindow;
diff --git a/tools/viewer/ParticlesSlide.cpp b/tools/viewer/ParticlesSlide.cpp
index 33141ee..4bf2575 100644
--- a/tools/viewer/ParticlesSlide.cpp
+++ b/tools/viewer/ParticlesSlide.cpp
@@ -347,7 +347,7 @@
     return true;
 }
 
-bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state, uint32_t modifiers) {
+bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state, ModifierKey modifiers) {
     if (gDragIndex == -1) {
         if (state == Window::kDown_InputState) {
             float bestDistance = kDragSize;
diff --git a/tools/viewer/ParticlesSlide.h b/tools/viewer/ParticlesSlide.h
index fcc0f55..d2b742a 100644
--- a/tools/viewer/ParticlesSlide.h
+++ b/tools/viewer/ParticlesSlide.h
@@ -30,7 +30,7 @@
     bool animate(const AnimTimer& timer) override;
 
     bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
-                 uint32_t modifiers) override;
+                 ModifierKey modifiers) override;
 
 private:
     void loadEffects(const char* dirname);
diff --git a/tools/viewer/SampleSlide.cpp b/tools/viewer/SampleSlide.cpp
index dc65a28..4c0108f 100644
--- a/tools/viewer/SampleSlide.cpp
+++ b/tools/viewer/SampleSlide.cpp
@@ -46,14 +46,7 @@
 }
 
 bool SampleSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state,
-                          uint32_t modifiers) {
-    // map to Sample::Click modifiers
-    unsigned modifierKeys = 0;
-    modifierKeys |= (modifiers & Window::kShift_ModifierKey) ? Sample::Click::kShift_ModifierKey : 0;
-    modifierKeys |= (modifiers & Window::kControl_ModifierKey) ? Sample::Click::kControl_ModifierKey : 0;
-    modifierKeys |= (modifiers & Window::kOption_ModifierKey) ? Sample::Click::kOption_ModifierKey : 0;
-    modifierKeys |= (modifiers & Window::kCommand_ModifierKey) ? Sample::Click::kCommand_ModifierKey : 0;
-
+                          ModifierKey modifierKeys) {
     bool handled = false;
     switch (state) {
         case Window::kDown_InputState: {
diff --git a/tools/viewer/SampleSlide.h b/tools/viewer/SampleSlide.h
index b9657d6..2672b7e 100644
--- a/tools/viewer/SampleSlide.h
+++ b/tools/viewer/SampleSlide.h
@@ -28,7 +28,7 @@
 
     bool onChar(SkUnichar c) override;
     bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
-                 uint32_t modifiers) override;
+                 ModifierKey modifiers) override;
 
 private:
     const SampleFactory fSampleFactory;
diff --git a/tools/viewer/SkottieSlide.cpp b/tools/viewer/SkottieSlide.cpp
index 1efe712..e638276 100644
--- a/tools/viewer/SkottieSlide.cpp
+++ b/tools/viewer/SkottieSlide.cpp
@@ -162,7 +162,7 @@
     return INHERITED::onChar(c);
 }
 
-bool SkottieSlide::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t) {
+bool SkottieSlide::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, ModifierKey) {
     switch (state) {
     case sk_app::Window::kUp_InputState:
         fShowAnimationInval = !fShowAnimationInval;
diff --git a/tools/viewer/SkottieSlide.h b/tools/viewer/SkottieSlide.h
index c267c1e..eadd65b 100644
--- a/tools/viewer/SkottieSlide.h
+++ b/tools/viewer/SkottieSlide.h
@@ -29,7 +29,7 @@
     bool animate(const AnimTimer&) override;
 
     bool onChar(SkUnichar) override;
-    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t modifiers) override;
+    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, ModifierKey modifiers) override;
 
 private:
     SkString                           fPath;
diff --git a/tools/viewer/Slide.h b/tools/viewer/Slide.h
index c3124ad..6f62faa 100644
--- a/tools/viewer/Slide.h
+++ b/tools/viewer/Slide.h
@@ -31,7 +31,7 @@
 
     virtual bool onChar(SkUnichar c) { return false; }
     virtual bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
-                         uint32_t modifiers) { return false; }
+                         ModifierKey modifiers) { return false; }
 
     virtual bool onGetControls(SkMetaData*) { return false; }
     virtual void onSetControls(const SkMetaData&) {}
diff --git a/tools/viewer/SlideDir.cpp b/tools/viewer/SlideDir.cpp
index 67c3f88..a8d84ae 100644
--- a/tools/viewer/SlideDir.cpp
+++ b/tools/viewer/SlideDir.cpp
@@ -158,7 +158,7 @@
         fState = State::kUnfocusing;
     }
 
-    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t modifiers) {
+    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, ModifierKey modifiers) {
         SkASSERT(fTarget);
 
         if (!fRect.contains(x, y)) {
@@ -379,8 +379,8 @@
 }
 
 bool SlideDir::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
-                       uint32_t modifiers) {
-    if (state == sk_app::Window::kMove_InputState || modifiers)
+                       ModifierKey modifiers) {
+    if (state == sk_app::Window::kMove_InputState || ModifierKeyIsSet(modifiers))
         return false;
 
     if (fFocusController->hasFocus()) {
diff --git a/tools/viewer/SlideDir.h b/tools/viewer/SlideDir.h
index 664d5ee..eb42c29 100644
--- a/tools/viewer/SlideDir.h
+++ b/tools/viewer/SlideDir.h
@@ -36,7 +36,7 @@
     bool animate(const AnimTimer&) override;
 
     bool onChar(SkUnichar) override;
-    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t modifiers) override;
+    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, ModifierKey modifiers) override;
 
 private:
     struct Rec;
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 125e2de..b45c65b 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -1375,7 +1375,7 @@
     }
 
     const auto slidePt = this->mapEvent(x, y);
-    if (fSlides[fCurrentSlide]->onMouse(slidePt.x(), slidePt.y(), state, 0)) {
+    if (fSlides[fCurrentSlide]->onMouse(slidePt.x(), slidePt.y(), state, ModifierKey::kNone)) {
         fWindow->inval();
         return true;
     }
@@ -1417,7 +1417,7 @@
     return true;
 }
 
-bool Viewer::onMouse(int x, int y, Window::InputState state, uint32_t modifiers) {
+bool Viewer::onMouse(int x, int y, Window::InputState state, ModifierKey modifiers) {
     if (GestureDevice::kTouch == fGestureDevice) {
         return false;
     }
@@ -2341,11 +2341,11 @@
     }
 }
 
-bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
+bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, ModifierKey modifiers) {
     return fCommands.onKey(key, state, modifiers);
 }
 
-bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
+bool Viewer::onChar(SkUnichar c, ModifierKey modifiers) {
     if (fSlides[fCurrentSlide]->onChar(c)) {
         fWindow->inval();
         return true;
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index 8cc2f21..c9d9914 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -38,10 +38,10 @@
     void onPaint(SkSurface*) override;
     void onResize(int width, int height) override;
     bool onTouch(intptr_t owner, sk_app::Window::InputState state, float x, float y) override;
-    bool onMouse(int x, int y, sk_app::Window::InputState state, uint32_t modifiers) override;
+    bool onMouse(int x, int y, sk_app::Window::InputState state, ModifierKey modifiers) override;
     void onUIStateChanged(const SkString& stateName, const SkString& stateValue) override;
-    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) override;
-    bool onChar(SkUnichar c, uint32_t modifiers) override;
+    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, ModifierKey modifiers) override;
+    bool onChar(SkUnichar c, ModifierKey modifiers) override;
 
     struct SkFontFields {
         bool fTypeface = false;