Bug 1421088 - Move code out of DrawWidgetBackground into a new method called ComputeWidgetInfo. r=spohl
authorMarkus Stange <mstange@themasta.com>
Sat, 14 Apr 2018 23:31:11 -0400
changeset 466958 86f9b0d937eaa65bb3ac26528c593361701b818f
parent 466957 90617339a4d1071dbf84df0d9d650e31bc180ccd
child 466959 af50acbd6c2884dbbb26b3c8053475318fd57697
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1421088
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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,