Bug 1421088 - Don't pass an nsIFrame* to DrawSpinButton / DrawSpinButtons. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Sat, 14 Apr 2018 22:14:19 -0400
changeset 782227 cfe60fa49b7db0371b61c9705b6f6a8b4778fc80
parent 782226 2ecf2682ed2b8f3e3b7ff55f261e1d8809ba5ccc
child 782228 8c5038bffa6591bbfe29df86a67d876169b39b74
push id106503
push userbmo:mstange@themasta.com
push dateSun, 15 Apr 2018 02:35:01 +0000
reviewersspohl
bugs1421088
milestone61.0a1
Bug 1421088 - Don't pass an nsIFrame* to DrawSpinButton / DrawSpinButtons. r?spohl MozReview-Commit-ID: AtY1eoiXcCa
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -69,16 +69,21 @@ public:
     eArrowButton,
     eHelpButton,
     eTreeTwistyPointingRight,
     eTreeTwistyPointingDown,
     eDisclosureButtonClosed,
     eDisclosureButtonOpen
   };
 
+  enum class SpinButton : uint8_t {
+    eUp,
+    eDown
+  };
+
   struct ControlParams {
     ControlParams()
       : disabled(false)
       , insideActiveWindow(false)
       , pressed(false)
       , focused(false)
       , rtl(false)
     {}
@@ -124,16 +129,22 @@ public:
   };
 
   struct DropdownParams {
     ControlParams controlParams;
     bool pullsDown = false;
     bool editable = false;
   };
 
+  struct SpinButtonParams {
+    mozilla::Maybe<SpinButton> pressedButton;
+    bool disabled = false;
+    bool insideActiveWindow = false;
+  };
+
   struct TreeHeaderCellParams {
     ControlParams controlParams;
     TreeSortDirection sortDirection = eTreeSortDirection_Natural;
     bool lastTreeHeaderCell = false;
   };
 
   nsNativeThemeCocoa();
 
@@ -256,25 +267,23 @@ protected:
                   const ButtonParams& aParams);
   void DrawTreeHeaderCell(CGContextRef context, const HIRect& inBoxRect,
                           const TreeHeaderCellParams& aParams);
   void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect,
                         mozilla::EventStates inState, uint8_t aWidgetType,
                         nsIFrame* aFrame);
   void DrawDropdown(CGContextRef context, const HIRect& inBoxRect,
                     const DropdownParams& aParams);
-  void DrawSpinButtons(CGContextRef context, ThemeButtonKind inKind,
-                       const HIRect& inBoxRect, ThemeDrawState inDrawState,
-                       ThemeButtonAdornment inAdornment,
-                       mozilla::EventStates inState, nsIFrame* aFrame);
-  void DrawSpinButton(CGContextRef context, ThemeButtonKind inKind,
-                      const HIRect& inBoxRect, ThemeDrawState inDrawState,
-                      ThemeButtonAdornment inAdornment,
-                      mozilla::EventStates inState,
-                      nsIFrame* aFrame, uint8_t aWidgetType);
+  HIThemeButtonDrawInfo SpinButtonDrawInfo(ThemeButtonKind aKind,
+                                           const SpinButtonParams& aParams);
+  void DrawSpinButtons(CGContextRef context, const HIRect& inBoxRect,
+                       const SpinButtonParams& aParams);
+  void DrawSpinButton(CGContextRef context,
+                      const HIRect& inBoxRect, SpinButton aDrawnButton,
+                      const SpinButtonParams& aParams);
   void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
                           NSWindow* aWindow);
   void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
                      nsIFrame *aFrame);
   void DrawResizer(CGContextRef cgContext, const HIRect& aRect, nsIFrame *aFrame);
 
   // Scrollbars
   nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -1884,73 +1884,73 @@ static const CellRenderSettings spinnerS
     { // Yosemite
       {0, 0, 0, 0},    // mini
       {0, 0, 0, 0},    // small
       {0, 0, 0, 0}     // regular
     }
   }
 };
 
-void
-nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
-                                    const HIRect& inBoxRect, ThemeDrawState inDrawState,
-                                    ThemeButtonAdornment inAdornment,
-                                    EventStates inState, nsIFrame* aFrame)
+HIThemeButtonDrawInfo
+nsNativeThemeCocoa::SpinButtonDrawInfo(ThemeButtonKind aKind,
+                                       const SpinButtonParams& aParams)
 {
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
   HIThemeButtonDrawInfo bdi;
   bdi.version = 0;
-  bdi.kind = inKind;
+  bdi.kind = aKind;
   bdi.value = kThemeButtonOff;
-  bdi.adornment = inAdornment;
-
-  if (IsDisabled(aFrame, inState))
+  bdi.adornment = kThemeAdornmentNone;
+
+  if (aParams.disabled) {
     bdi.state = kThemeStateUnavailable;
-  else
-    bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive;
-
+  } else if (aParams.insideActiveWindow && aParams.pressedButton) {
+    if (*aParams.pressedButton == SpinButton::eUp) {
+      bdi.state = kThemeStatePressedUp;
+    } else {
+      bdi.state = kThemeStatePressedDown;
+    }
+  } else {
+    bdi.state = kThemeStateActive;
+  }
+
+  return bdi;
+}
+
+void
+nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext,
+                                    const HIRect& inBoxRect,
+                                    const SpinButtonParams& aParams)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+  HIThemeButtonDrawInfo bdi =
+    SpinButtonDrawInfo(kThemeIncDecButton, aParams);
   HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 nsNativeThemeCocoa::DrawSpinButton(CGContextRef cgContext,
-                                   ThemeButtonKind inKind,
                                    const HIRect& inBoxRect,
-                                   ThemeDrawState inDrawState,
-                                   ThemeButtonAdornment inAdornment,
-                                   EventStates inState,
-                                   nsIFrame* aFrame,
-                                   uint8_t aWidgetType)
+                                   SpinButton aDrawnButton,
+                                   const SpinButtonParams& aParams)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  MOZ_ASSERT(aWidgetType == NS_THEME_SPINNER_UPBUTTON ||
-             aWidgetType == NS_THEME_SPINNER_DOWNBUTTON);
-
-  HIThemeButtonDrawInfo bdi;
-  bdi.version = 0;
-  bdi.kind = inKind;
-  bdi.value = kThemeButtonOff;
-  bdi.adornment = inAdornment;
-
-  if (IsDisabled(aFrame, inState))
-    bdi.state = kThemeStateUnavailable;
-  else
-    bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive;
+  HIThemeButtonDrawInfo bdi =
+    SpinButtonDrawInfo(kThemeIncDecButtonMini, aParams);
 
   // Cocoa only allows kThemeIncDecButton to paint the up and down spin buttons
   // together as a single unit (presumably because when one button is active,
   // the appearance of both changes (in different ways)). Here we have to paint
   // both buttons, using clip to hide the one we don't want to paint.
   HIRect drawRect = inBoxRect;
   drawRect.size.height *= 2;
-  if (aWidgetType == NS_THEME_SPINNER_DOWNBUTTON) {
+  if (aDrawnButton == SpinButton::eDown) {
     drawRect.origin.y -= inBoxRect.size.height;
   }
 
   // Shift the drawing a little to the left, since cocoa paints with more
   // blank space around the visual buttons than we'd like:
   drawRect.origin.x -= 1;
 
   CGContextSaveGState(cgContext);
@@ -2829,45 +2829,51 @@ nsNativeThemeCocoa::DrawWidgetBackground
       bool isSpinner = (aWidgetType == NS_THEME_SPINNER);
       nsIContent* content = aFrame->GetContent();
       if (isSpinner && content->IsHTMLElement()) {
         // In HTML the theming for the spin buttons is drawn individually into
         // their own backgrounds instead of being drawn into the background of
         // their spinner parent as it is for XUL.
         break;
       }
-      ThemeDrawState state = kThemeStateActive;
+      SpinButtonParams params;
       if (content->IsElement()) {
         if (content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state,
                                               NS_LITERAL_STRING("up"), eCaseMatters)) {
-          state = kThemeStatePressedUp;
+          params.pressedButton = Some(SpinButton::eUp);
         } else if (content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state,
                                                      NS_LITERAL_STRING("down"), eCaseMatters)) {
-          state = kThemeStatePressedDown;
+          params.pressedButton = Some(SpinButton::eDown);
         }
       }
-
-      DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, state,
-                      kThemeAdornmentNone, eventState, aFrame);
+      params.disabled = IsDisabled(aFrame, eventState);
+      params.insideActiveWindow = FrameIsInActiveWindow(aFrame);
+
+      DrawSpinButtons(cgContext, macRect, params);
     }
       break;
 
     case NS_THEME_SPINNER_UPBUTTON:
     case NS_THEME_SPINNER_DOWNBUTTON: {
       nsNumberControlFrame* numberControlFrame =
         nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
       if (numberControlFrame) {
-        ThemeDrawState state = kThemeStateActive;
+        SpinButtonParams params;
         if (numberControlFrame->SpinnerUpButtonIsDepressed()) {
-          state = kThemeStatePressedUp;
+          params.pressedButton = Some(SpinButton::eUp);
         } else if (numberControlFrame->SpinnerDownButtonIsDepressed()) {
-          state = kThemeStatePressedDown;
+          params.pressedButton = Some(SpinButton::eDown);
         }
-        DrawSpinButton(cgContext, kThemeIncDecButtonMini, macRect, state,
-                       kThemeAdornmentNone, eventState, aFrame, aWidgetType);
+        params.disabled = IsDisabled(aFrame, eventState);
+        params.insideActiveWindow = FrameIsInActiveWindow(aFrame);
+        if (aWidgetType == NS_THEME_SPINNER_UPBUTTON) {
+          DrawSpinButton(cgContext, macRect, SpinButton::eUp, params);
+        } else {
+          DrawSpinButton(cgContext, macRect, SpinButton::eDown, params);
+        }
       }
     }
       break;
 
     case NS_THEME_TOOLBARBUTTON:
       DrawSegment(cgContext, macRect, eventState, aFrame, toolbarButtonRenderSettings);
       break;