Bug 1421088 - Move code out of DrawWidgetBackground into a new method called ComputeWidgetInfo. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Sat, 14 Apr 2018 23:31:11 -0400
changeset 782264 3fba8e562253d5f90e70e76b1cf29de5c98064a5
parent 782263 774c4b62aaf23745392e5918b0ec259ffd8d6df6
push id106506
push userbmo:mstange@themasta.com
push dateSun, 15 Apr 2018 03:32:46 +0000
reviewersspohl
bugs1421088
milestone61.0a1
Bug 1421088 - Move code out of DrawWidgetBackground into a new method called ComputeWidgetInfo. r?spohl MozReview-Commit-ID: 2XeZHH4lJrj
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -404,17 +404,19 @@ public:
   bool ThemeDrawsFocusForWidget(uint8_t aWidgetType) override;
   bool ThemeNeedsComboboxDropmarker() override;
   virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) override;
   virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame,
                                                  uint8_t aWidgetType) override;
   virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame,
                                                        uint8_t aWidgetType) override;
   virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) override;
-
+  mozilla::Maybe<WidgetInfo> ComputeWidgetInfo(nsIFrame* aFrame,
+                                               uint8_t aWidgetType,
+                                               const nsRect& aRect);
   void DrawProgress(CGContextRef context, const HIRect& inBoxRect,
                     const ProgressParams& aParams);
 
   static void DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
                                  CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped);
 
 protected:
   virtual ~nsNativeThemeCocoa();
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2837,122 +2837,107 @@ nsNativeThemeCocoa::IsParentScrollbarRol
 
 static bool
 IsHiDPIContext(nsDeviceContext* aContext)
 {
   return nsPresContext::AppUnitsPerCSSPixel() >=
     2 * aContext->AppUnitsPerDevPixelAtUnitFullZoom();
 }
 
-NS_IMETHODIMP
-nsNativeThemeCocoa::DrawWidgetBackground(gfxContext* aContext,
-                                         nsIFrame* aFrame,
-                                         uint8_t aWidgetType,
-                                         const nsRect& aRect,
-                                         const nsRect& aDirtyRect)
+Maybe<nsNativeThemeCocoa::WidgetInfo>
+nsNativeThemeCocoa::ComputeWidgetInfo(nsIFrame* aFrame,
+                                      uint8_t aWidgetType,
+                                      const nsRect& aRect)
 {
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   // setup to draw into the correct port
   int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel();
 
   gfx::Rect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
   nativeWidgetRect.Scale(1.0 / gfxFloat(p2a));
   float originalHeight = nativeWidgetRect.Height();
   nativeWidgetRect.Round();
-  if (nativeWidgetRect.IsEmpty())
-    return NS_OK; // Don't attempt to draw invisible widgets.
+  if (nativeWidgetRect.IsEmpty()) {
+    return Nothing(); // Don't attempt to draw invisible widgets.
+  }
 
   bool hidpi = IsHiDPIContext(aFrame->PresContext()->DeviceContext());
   if (hidpi) {
     // Use high-resolution drawing.
     nativeWidgetRect.Scale(0.5f);
     originalHeight *= 0.5f;
   }
 
-  Maybe<WidgetInfo> widgetInfo;
-
   EventStates eventState = GetContentState(aFrame, aWidgetType);
 
   switch (aWidgetType) {
     case NS_THEME_DIALOG:
       if (IsWindowSheet(aFrame)) {
         if (VibrancyManager::SystemSupportsVibrancy()) {
           ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-          widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
-        } else {
-          widgetInfo = Some(WidgetInfo::SheetBackground());
+          return Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
         }
-      } else {
-        widgetInfo = Some(WidgetInfo::DialogBackground());
+        return Some(WidgetInfo::SheetBackground());
       }
-      break;
+      return Some(WidgetInfo::DialogBackground());
 
     case NS_THEME_MENUPOPUP:
-      widgetInfo = Some(WidgetInfo::MenuBackground(
+      return Some(WidgetInfo::MenuBackground(
         ComputeMenuBackgroundParams(aFrame, eventState)));
-      break;
 
     case NS_THEME_MENUARROW:
-      widgetInfo = Some(WidgetInfo::MenuIcon(
+      return Some(WidgetInfo::MenuIcon(
         ComputeMenuIconParams(aFrame, eventState,
                               MenuIcon::eMenuArrow)));
-      break;
 
     case NS_THEME_MENUITEM:
     case NS_THEME_CHECKMENUITEM:
-      widgetInfo = Some(WidgetInfo::MenuItem(
+      return Some(WidgetInfo::MenuItem(
         ComputeMenuItemParams(aFrame, eventState,
                               aWidgetType == NS_THEME_CHECKMENUITEM)));
-      break;
 
     case NS_THEME_MENUSEPARATOR:
-      widgetInfo = Some(WidgetInfo::MenuSeparator(
+      return Some(WidgetInfo::MenuSeparator(
         ComputeMenuItemParams(aFrame, eventState, false)));
-      break;
 
     case NS_THEME_BUTTON_ARROW_UP:
     case NS_THEME_BUTTON_ARROW_DOWN: {
       MenuIcon icon =
         aWidgetType == NS_THEME_BUTTON_ARROW_UP ? MenuIcon::eMenuUpScrollArrow
                                                 : MenuIcon::eMenuDownScrollArrow;
-      widgetInfo = Some(WidgetInfo::MenuIcon(
+      return Some(WidgetInfo::MenuIcon(
         ComputeMenuIconParams(aFrame, eventState, icon)));
     }
-      break;
 
     case NS_THEME_TOOLTIP:
       if (VibrancyManager::SystemSupportsVibrancy()) {
         ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
-      } else {
-        widgetInfo = Some(WidgetInfo::Tooltip());
+        return Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       }
-      break;
+      return Some(WidgetInfo::Tooltip());
 
     case NS_THEME_CHECKBOX:
     case NS_THEME_RADIO: {
       bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
 
       CheckboxOrRadioParams params;
       params.state = CheckboxOrRadioState::eOff;
       if (isCheckbox && GetIndeterminate(aFrame)) {
         params.state = CheckboxOrRadioState::eIndeterminate;
       } else if (GetCheckedOrSelected(aFrame, !isCheckbox)) {
         params.state = CheckboxOrRadioState::eOn;
       }
       params.controlParams = ComputeControlParams(aFrame, eventState);
       params.verticalAlignFactor = VerticalAlignFactor(aFrame);
       if (isCheckbox) {
-        widgetInfo = Some(WidgetInfo::Checkbox(params));
-      } else {
-        widgetInfo = Some(WidgetInfo::Radio(params));
+        return Some(WidgetInfo::Checkbox(params));
       }
+      return Some(WidgetInfo::Radio(params));
     }
-      break;
 
     case NS_THEME_BUTTON:
       if (IsDefaultButton(aFrame)) {
         // Check whether the default button is in a document that does not
         // match the :-moz-window-inactive pseudoclass. This activeness check
         // is different from the other "active window" checks in this file
         // because we absolutely need the button's default button appearance to
         // be in sync with its text color, and the text color is changed by
@@ -2968,73 +2953,69 @@ nsNativeThemeCocoa::DrawWidgetBackground
         }
         bool hasDefaultButtonLook =
           isInActiveWindow && !eventState.HasState(NS_EVENT_STATE_ACTIVE);
         ButtonType buttonType =
           hasDefaultButtonLook ? ButtonType::eDefaultPushButton
                                : ButtonType::eRegularPushButton;
         ControlParams params = ComputeControlParams(aFrame, eventState);
         params.insideActiveWindow = isInActiveWindow;
-        widgetInfo = Some(WidgetInfo::Button(ButtonParams{params, buttonType}));
-      } else if (IsButtonTypeMenu(aFrame)) {
+        return Some(WidgetInfo::Button(ButtonParams{params, buttonType}));
+      }
+      if (IsButtonTypeMenu(aFrame)) {
         ControlParams controlParams = ComputeControlParams(aFrame, eventState);
         controlParams.focused = controlParams.focused || IsFocused(aFrame);
         controlParams.pressed = IsOpenButton(aFrame);
         DropdownParams params;
         params.controlParams = controlParams;
         params.pullsDown = true;
         params.editable = false;
-        widgetInfo = Some(WidgetInfo::Dropdown(params));
-      } else if (originalHeight > DO_SQUARE_BUTTON_HEIGHT) {
+        return Some(WidgetInfo::Dropdown(params));
+      }
+      if (originalHeight > DO_SQUARE_BUTTON_HEIGHT) {
         // If the button is tall enough, draw the square button style so that
         // buttons with non-standard content look good. Otherwise draw normal
         // rounded aqua buttons.
         // This comparison is done based on the height that is calculated without
         // the top, because the snapped height can be affected by the top of the
         // rect and that may result in different height depending on the top value.
-        widgetInfo = Some(WidgetInfo::Button(
+        return Some(WidgetInfo::Button(
           ButtonParams{ComputeControlParams(aFrame, eventState),
                        ButtonType::eSquareBezelPushButton}));
-      } else {
-        widgetInfo = Some(WidgetInfo::Button(
-          ButtonParams{ComputeControlParams(aFrame, eventState),
-                       ButtonType::eRoundedBezelPushButton}));
       }
-      break;
+      return Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                     ButtonType::eRoundedBezelPushButton}));
 
     case NS_THEME_FOCUS_OUTLINE:
-      widgetInfo = Some(WidgetInfo::FocusOutline());
-      break;
+      return Some(WidgetInfo::FocusOutline());
 
     case NS_THEME_MAC_HELP_BUTTON:
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
-                      ButtonType::eHelpButton}));
-      break;
+                     ButtonType::eHelpButton}));
 
     case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN:
     case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: {
       ButtonType buttonType = (aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED)
         ? ButtonType::eDisclosureButtonClosed : ButtonType::eDisclosureButtonOpen;
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
-                    buttonType}));
+                     buttonType}));
     }
-      break;
 
     case NS_THEME_BUTTON_BEVEL: {
       bool isDefaultButton = IsDefaultButton(aFrame);
       ButtonType buttonType =
         isDefaultButton ? ButtonType::eDefaultBevelButton
                         : ButtonType::eRegularBevelButton;
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
-                    buttonType}));
+                     buttonType}));
     }
-      break;
 
     case NS_THEME_INNER_SPIN_BUTTON: {
     case NS_THEME_SPINNER:
       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
@@ -3049,306 +3030,293 @@ nsNativeThemeCocoa::DrawWidgetBackground
         } else if (content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state,
                                                      NS_LITERAL_STRING("down"), eCaseMatters)) {
           params.pressedButton = Some(SpinButton::eDown);
         }
       }
       params.disabled = IsDisabled(aFrame, eventState);
       params.insideActiveWindow = FrameIsInActiveWindow(aFrame);
 
-      widgetInfo = Some(WidgetInfo::SpinButtons(params));
+      return Some(WidgetInfo::SpinButtons(params));
     }
-      break;
 
     case NS_THEME_SPINNER_UPBUTTON:
     case NS_THEME_SPINNER_DOWNBUTTON: {
       nsNumberControlFrame* numberControlFrame =
         nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
       if (numberControlFrame) {
         SpinButtonParams params;
         if (numberControlFrame->SpinnerUpButtonIsDepressed()) {
           params.pressedButton = Some(SpinButton::eUp);
         } else if (numberControlFrame->SpinnerDownButtonIsDepressed()) {
           params.pressedButton = Some(SpinButton::eDown);
         }
         params.disabled = IsDisabled(aFrame, eventState);
         params.insideActiveWindow = FrameIsInActiveWindow(aFrame);
         if (aWidgetType == NS_THEME_SPINNER_UPBUTTON) {
-          widgetInfo = Some(WidgetInfo::SpinButtonUp(params));
-        } else {
-          widgetInfo = Some(WidgetInfo::SpinButtonDown(params));
+          return Some(WidgetInfo::SpinButtonUp(params));
         }
+        return Some(WidgetInfo::SpinButtonDown(params));
       }
     }
       break;
 
     case NS_THEME_TOOLBARBUTTON: {
       SegmentParams params =
         ComputeSegmentParams(aFrame, eventState, SegmentType::eToolbarButton);
       params.insideActiveWindow = [NativeWindowForFrame(aFrame) isMainWindow];
-      widgetInfo = Some(WidgetInfo::Segment(params));
+      return Some(WidgetInfo::Segment(params));
     }
-      break;
 
     case NS_THEME_SEPARATOR:
-      widgetInfo = Some(WidgetInfo::Separator());
-      break;
+      return Some(WidgetInfo::Separator());
 
     case NS_THEME_TOOLBAR: {
       NSWindow* win = NativeWindowForFrame(aFrame);
       bool isMain = [win isMainWindow];
       if (ToolbarCanBeUnified(nativeWidgetRect, win)) {
         float unifiedHeight =
           std::max(float([(ToolbarWindow*)win unifiedToolbarHeight]),
                    nativeWidgetRect.Height());
-        widgetInfo = Some(WidgetInfo::UnifiedToolbar(
+        return Some(WidgetInfo::UnifiedToolbar(
           UnifiedToolbarParams{unifiedHeight, isMain}));
-      } else {
-        widgetInfo = Some(WidgetInfo::Toolbar(isMain));
       }
+      return Some(WidgetInfo::Toolbar(isMain));
     }
-      break;
 
     case NS_THEME_WINDOW_TITLEBAR: {
       NSWindow* win = NativeWindowForFrame(aFrame);
       bool isMain = [win isMainWindow];
       float unifiedToolbarHeight = [win isKindOfClass:[ToolbarWindow class]] ?
         [(ToolbarWindow*)win unifiedToolbarHeight] : nativeWidgetRect.Height();
-      widgetInfo = Some(WidgetInfo::NativeTitlebar(
+      return Some(WidgetInfo::NativeTitlebar(
         UnifiedToolbarParams{unifiedToolbarHeight, isMain}));
     }
-      break;
 
     case NS_THEME_STATUSBAR:
-      widgetInfo = Some(WidgetInfo::StatusBar(IsActive(aFrame, YES)));
-      break;
+      return Some(WidgetInfo::StatusBar(IsActive(aFrame, YES)));
 
     case NS_THEME_MENULIST:
     case NS_THEME_MENULIST_TEXTFIELD: {
       ControlParams controlParams = ComputeControlParams(aFrame, eventState);
       controlParams.focused = controlParams.focused || IsFocused(aFrame);
       controlParams.pressed = IsOpenButton(aFrame);
       DropdownParams params;
       params.controlParams = controlParams;
       params.pullsDown = false;
       params.editable = aWidgetType == NS_THEME_MENULIST_TEXTFIELD;
-      widgetInfo = Some(WidgetInfo::Dropdown(params));
+      return Some(WidgetInfo::Dropdown(params));
     }
-      break;
 
     case NS_THEME_MENULIST_BUTTON:
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
-                    ButtonType::eArrowButton}));
-      break;
+                     ButtonType::eArrowButton}));
 
     case NS_THEME_GROUPBOX:
-      widgetInfo = Some(WidgetInfo::GroupBox());
-      break;
+      return Some(WidgetInfo::GroupBox());
 
     case NS_THEME_TEXTFIELD:
     case NS_THEME_NUMBER_INPUT: {
       bool isFocused = eventState.HasState(NS_EVENT_STATE_FOCUS);
       // XUL textboxes set the native appearance on the containing box, while
       // concrete focus is set on the html:input element within it. We can
       // though, check the focused attribute of xul textboxes in this case.
       // On Mac, focus rings are always shown for textboxes, so we do not need
       // to check the window's focus ring state here
       if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) {
         isFocused = true;
       }
 
       bool isDisabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
-      widgetInfo = Some(WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused}));
-      break;
+      return Some(WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused}));
     }
 
     case NS_THEME_SEARCHFIELD:
-      widgetInfo = Some(WidgetInfo::SearchField(
+      return Some(WidgetInfo::SearchField(
         ComputeSearchFieldParams(aFrame, eventState)));
-      break;
 
     case NS_THEME_PROGRESSBAR:
     {
       // Don't request repaints for scrollbars at 100% because those don't animate.
       if (GetProgressValue(aFrame) < GetProgressMaxValue(aFrame)) {
         if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
           NS_WARNING("Unable to animate progressbar!");
         }
       }
-      widgetInfo = Some(WidgetInfo::ProgressBar(
+      return Some(WidgetInfo::ProgressBar(
         ComputeProgressParams(aFrame, eventState,
                               !IsVerticalProgress(aFrame))));
-      break;
     }
 
     case NS_THEME_PROGRESSBAR_VERTICAL:
-      widgetInfo = Some(WidgetInfo::ProgressBar(
+      return Some(WidgetInfo::ProgressBar(
         ComputeProgressParams(aFrame, eventState, false)));
-      break;
 
     case NS_THEME_METERBAR:
-      widgetInfo = Some(WidgetInfo::Meter(ComputeMeterParams(aFrame)));
-      break;
+      return Some(WidgetInfo::Meter(ComputeMeterParams(aFrame)));
 
     case NS_THEME_PROGRESSCHUNK:
     case NS_THEME_PROGRESSCHUNK_VERTICAL:
     case NS_THEME_METERCHUNK:
       // Do nothing: progress and meter bars cases will draw chunks.
       break;
 
     case NS_THEME_TREETWISTY:
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
                      ButtonType::eTreeTwistyPointingRight}));
-      break;
 
     case NS_THEME_TREETWISTYOPEN:
-      widgetInfo = Some(WidgetInfo::Button(
+      return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
                      ButtonType::eTreeTwistyPointingDown}));
-      break;
 
     case NS_THEME_TREEHEADERCELL:
-      widgetInfo = Some(WidgetInfo::TreeHeaderCell(
+      return Some(WidgetInfo::TreeHeaderCell(
         ComputeTreeHeaderCellParams(aFrame, eventState)));
-      break;
 
     case NS_THEME_TREEITEM:
     case NS_THEME_TREEVIEW:
-      widgetInfo = Some(WidgetInfo::ColorFill(Color(1.0, 1.0, 1.0, 1.0)));
-      break;
+      return Some(WidgetInfo::ColorFill(Color(1.0, 1.0, 1.0, 1.0)));
 
     case NS_THEME_TREEHEADER:
       // do nothing, taken care of by individual header cells
     case NS_THEME_TREEHEADERSORTARROW:
       // do nothing, taken care of by treeview header
     case NS_THEME_TREELINE:
       // do nothing, these lines don't exist on macos
       break;
 
     case NS_THEME_SCALE_HORIZONTAL:
     case NS_THEME_SCALE_VERTICAL:
-      widgetInfo = Some(WidgetInfo::Scale(
+      return Some(WidgetInfo::Scale(
         ComputeXULScaleParams(aFrame, eventState,
                               aWidgetType == NS_THEME_SCALE_HORIZONTAL)));
-      break;
 
     case NS_THEME_SCALETHUMB_HORIZONTAL:
     case NS_THEME_SCALETHUMB_VERTICAL:
       // do nothing, drawn by scale
       break;
 
     case NS_THEME_RANGE: {
       Maybe<ScaleParams> params = ComputeHTMLScaleParams(aFrame, eventState);
       if (params) {
-        widgetInfo = Some(WidgetInfo::Scale(*params));
+        return Some(WidgetInfo::Scale(*params));
       }
       break;
     }
 
     case NS_THEME_SCROLLBAR_SMALL:
     case NS_THEME_SCROLLBAR:
       break;
     case NS_THEME_SCROLLBARTHUMB_VERTICAL:
     case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
-      widgetInfo = Some(WidgetInfo::ScrollbarThumb(
+      return Some(WidgetInfo::ScrollbarThumb(
         ComputeScrollbarParams(
           aFrame, aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL)));
-      break;
 
     case NS_THEME_SCROLLBARBUTTON_UP:
     case NS_THEME_SCROLLBARBUTTON_LEFT:
     case NS_THEME_SCROLLBARBUTTON_DOWN:
     case NS_THEME_SCROLLBARBUTTON_RIGHT:
       break;
 
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
-      widgetInfo = Some(WidgetInfo::ScrollbarTrack(
+      return Some(WidgetInfo::ScrollbarTrack(
         ComputeScrollbarParams(
           aFrame, aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL)));
-      break;
 
     case NS_THEME_TEXTFIELD_MULTILINE:
-      widgetInfo = Some(WidgetInfo::MultilineTextField(
+      return Some(WidgetInfo::MultilineTextField(
         eventState.HasState(NS_EVENT_STATE_FOCUS)));
-      break;
 
     case NS_THEME_LISTBOX:
-      widgetInfo = Some(WidgetInfo::ListBox());
-      break;
+      return Some(WidgetInfo::ListBox());
 
     case NS_THEME_MAC_SOURCE_LIST: {
       if (VibrancyManager::SystemSupportsVibrancy()) {
         ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
-      } else {
-        widgetInfo = Some(WidgetInfo::SourceList(FrameIsInActiveWindow(aFrame)));
+        return Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       }
+      return Some(WidgetInfo::SourceList(FrameIsInActiveWindow(aFrame)));
     }
-      break;
 
     case NS_THEME_MAC_SOURCE_LIST_SELECTION:
     case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: {
       // If we're in XUL tree, we need to rely on the source list's clear
       // background display item. If we cleared the background behind the
       // selections, the source list would not pick up the right font
       // smoothing background. So, to simplify a bit, we only support vibrancy
       // if we're in a source list.
       if (VibrancyManager::SystemSupportsVibrancy() && IsInSourceList(aFrame)) {
         ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
-      } else {
-        bool isInActiveWindow = FrameIsInActiveWindow(aFrame);
-        if (aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION) {
-          widgetInfo = Some(WidgetInfo::ActiveSourceListSelection(isInActiveWindow));
-        } else {
-          widgetInfo = Some(WidgetInfo::InactiveSourceListSelection(isInActiveWindow));
-        }
+        return Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       }
+      bool isInActiveWindow = FrameIsInActiveWindow(aFrame);
+      if (aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION) {
+        return Some(WidgetInfo::ActiveSourceListSelection(isInActiveWindow));
+      }
+      return Some(WidgetInfo::InactiveSourceListSelection(isInActiveWindow));
     }
-      break;
 
     case NS_THEME_TAB: {
       SegmentParams params =
         ComputeSegmentParams(aFrame, eventState, SegmentType::eTab);
       params.pressed = params.pressed && !params.selected;
-      widgetInfo = Some(WidgetInfo::Segment(params));
+      return Some(WidgetInfo::Segment(params));
     }
-      break;
 
     case NS_THEME_TABPANELS:
-      widgetInfo = Some(WidgetInfo::TabPanel(FrameIsInActiveWindow(aFrame)));
-      break;
+      return Some(WidgetInfo::TabPanel(FrameIsInActiveWindow(aFrame)));
 
     case NS_THEME_RESIZER:
-      widgetInfo = Some(WidgetInfo::Resizer(IsFrameRTL(aFrame)));
-      break;
+      return Some(WidgetInfo::Resizer(IsFrameRTL(aFrame)));
 
     case NS_THEME_MAC_VIBRANCY_LIGHT:
     case NS_THEME_MAC_VIBRANCY_DARK:
     case NS_THEME_MAC_VIBRANT_TITLEBAR_LIGHT:
     case NS_THEME_MAC_VIBRANT_TITLEBAR_DARK: {
       ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-      widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
-      break;
+      return Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
     }
   }
 
-  if (hidpi) {
-    // Restore device pixel nativeWidgetRect.
-    nativeWidgetRect.Scale(2.0f);
+  return Nothing();
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(Nothing());
+}
+
+NS_IMETHODIMP
+nsNativeThemeCocoa::DrawWidgetBackground(gfxContext* aContext,
+                                         nsIFrame* aFrame,
+                                         uint8_t aWidgetType,
+                                         const nsRect& aRect,
+                                         const nsRect& aDirtyRect)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  Maybe<WidgetInfo> widgetInfo = ComputeWidgetInfo(aFrame, aWidgetType, aRect);
+
+  if (!widgetInfo) {
+    return NS_OK;
   }
 
-  if (widgetInfo) {
-    RenderWidget(*widgetInfo, *aContext->GetDrawTarget(),
-                 nativeWidgetRect, NSRectToRect(aDirtyRect, p2a),
-                 hidpi ? 2.0f : 1.0f);
-  }
+  int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel();
+
+  gfx::Rect nativeWidgetRect = NSRectToRect(aRect, p2a);
+  nativeWidgetRect.Round();
+
+  bool hidpi = IsHiDPIContext(aFrame->PresContext()->DeviceContext());
+
+  RenderWidget(*widgetInfo, *aContext->GetDrawTarget(),
+               nativeWidgetRect, NSRectToRect(aDirtyRect, p2a),
+               hidpi ? 2.0f : 1.0f);
+
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 void
 nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo,
                                  DrawTarget& aDrawTarget,