Bug 1421088 - Create a WidgetInfo struct and route drawing through it. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Sat, 14 Apr 2018 23:19:18 -0400
changeset 782262 71319785558289325670bcd54adc362d916943c1
parent 782261 9ec69098234c1b7c27a45ed6b4a38dbb539c433c
child 782263 774c4b62aaf23745392e5918b0ec259ffd8d6df6
push id106506
push userbmo:mstange@themasta.com
push dateSun, 15 Apr 2018 03:32:46 +0000
reviewersspohl
bugs1421088
milestone61.0a1
Bug 1421088 - Create a WidgetInfo struct and route drawing through it. r?spohl MozReview-Commit-ID: 1pKgNAodbev
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsNativeThemeCocoa_h_
 #define nsNativeThemeCocoa_h_
 
 #import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 
+#include "mozilla/Variant.h"
+
 #include "nsITheme.h"
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
 #include "nsNativeTheme.h"
 
 @class CellDrawView;
 @class NSProgressBarCell;
 class nsDeviceContext;
@@ -232,16 +234,136 @@ public:
     bool overlay : 1;
     bool rolledOver : 1;
     bool small : 1;
     bool horizontal : 1;
     bool rtl : 1;
     bool onDarkBackground : 1;
   };
 
+  enum Widget : uint8_t {
+    eColorFill,                    // mozilla::gfx::Color
+    eSheetBackground,
+    eDialogBackground,
+    eMenuBackground,               // MenuBackgroundParams
+    eMenuIcon,                     // MenuIconParams
+    eMenuItem,                     // MenuItemParams
+    eMenuSeparator,                // MenuItemParams
+    eTooltip,
+    eCheckbox,                     // CheckboxOrRadioParams
+    eRadio,                        // CheckboxOrRadioParams
+    eButton,                       // ButtonParams
+    eDropdown,                     // DropdownParams
+    eFocusOutline,
+    eSpinButtons,                  // SpinButtonParams
+    eSpinButtonUp,                 // SpinButtonParams
+    eSpinButtonDown,               // SpinButtonParams
+    eSegment,                      // SegmentParams
+    eSeparator,
+    eUnifiedToolbar,               // UnifiedToolbarParams
+    eToolbar,                      // bool
+    eNativeTitlebar,               // UnifiedToolbarParams
+    eStatusBar,                    // bool
+    eGroupBox,
+    eTextBox,                      // TextBoxParams
+    eSearchField,                  // SearchFieldParams
+    eProgressBar,                  // ProgressParams
+    eMeter,                        // MeterParams
+    eTreeHeaderCell,               // TreeHeaderCellParams
+    eScale,                        // ScaleParams
+    eScrollbarThumb,               // ScrollbarParams
+    eScrollbarTrack,               // ScrollbarParams
+    eMultilineTextField,           // bool
+    eListBox,
+    eSourceList,                   // bool
+    eActiveSourceListSelection,    // bool
+    eInactiveSourceListSelection,  // bool
+    eTabPanel,
+    eResizer
+  };
+
+  struct WidgetInfo {
+    static WidgetInfo ColorFill(const mozilla::gfx::Color& aParams) { return WidgetInfo(Widget::eColorFill, aParams); }
+    static WidgetInfo SheetBackground() { return WidgetInfo(Widget::eSheetBackground, false); }
+    static WidgetInfo DialogBackground() { return WidgetInfo(Widget::eDialogBackground, false); }
+    static WidgetInfo MenuBackground(const MenuBackgroundParams& aParams) { return WidgetInfo(Widget::eMenuBackground, aParams); }
+    static WidgetInfo MenuIcon(const MenuIconParams& aParams) { return WidgetInfo(Widget::eMenuIcon, aParams); }
+    static WidgetInfo MenuItem(const MenuItemParams& aParams) { return WidgetInfo(Widget::eMenuItem, aParams); }
+    static WidgetInfo MenuSeparator(const MenuItemParams& aParams) { return WidgetInfo(Widget::eMenuSeparator, aParams); }
+    static WidgetInfo Tooltip() { return WidgetInfo(Widget::eTooltip, false); }
+    static WidgetInfo Checkbox(const CheckboxOrRadioParams& aParams) { return WidgetInfo(Widget::eCheckbox, aParams); }
+    static WidgetInfo Radio(const CheckboxOrRadioParams& aParams) { return WidgetInfo(Widget::eRadio, aParams); }
+    static WidgetInfo Button(const ButtonParams& aParams) { return WidgetInfo(Widget::eButton, aParams); }
+    static WidgetInfo Dropdown(const DropdownParams& aParams) { return WidgetInfo(Widget::eDropdown, aParams); }
+    static WidgetInfo FocusOutline() { return WidgetInfo(Widget::eFocusOutline, false); }
+    static WidgetInfo SpinButtons(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtons, aParams); }
+    static WidgetInfo SpinButtonUp(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtonUp, aParams); }
+    static WidgetInfo SpinButtonDown(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtonDown, aParams); }
+    static WidgetInfo Segment(const SegmentParams& aParams) { return WidgetInfo(Widget::eSegment, aParams); }
+    static WidgetInfo Separator() { return WidgetInfo(Widget::eSeparator, false); }
+    static WidgetInfo UnifiedToolbar(const UnifiedToolbarParams& aParams) { return WidgetInfo(Widget::eUnifiedToolbar, aParams); }
+    static WidgetInfo Toolbar(bool aParams) { return WidgetInfo(Widget::eToolbar, aParams); }
+    static WidgetInfo NativeTitlebar(const UnifiedToolbarParams& aParams) { return WidgetInfo(Widget::eNativeTitlebar, aParams); }
+    static WidgetInfo StatusBar(bool aParams) { return WidgetInfo(Widget::eStatusBar, aParams); }
+    static WidgetInfo GroupBox() { return WidgetInfo(Widget::eGroupBox, false); }
+    static WidgetInfo TextBox(const TextBoxParams& aParams) { return WidgetInfo(Widget::eTextBox, aParams); }
+    static WidgetInfo SearchField(const SearchFieldParams& aParams) { return WidgetInfo(Widget::eSearchField, aParams); }
+    static WidgetInfo ProgressBar(const ProgressParams& aParams) { return WidgetInfo(Widget::eProgressBar, aParams); }
+    static WidgetInfo Meter(const MeterParams& aParams) { return WidgetInfo(Widget::eMeter, aParams); }
+    static WidgetInfo TreeHeaderCell(const TreeHeaderCellParams& aParams) { return WidgetInfo(Widget::eTreeHeaderCell, aParams); }
+    static WidgetInfo Scale(const ScaleParams& aParams) { return WidgetInfo(Widget::eScale, aParams); }
+    static WidgetInfo ScrollbarThumb(const ScrollbarParams& aParams) { return WidgetInfo(Widget::eScrollbarThumb, aParams); }
+    static WidgetInfo ScrollbarTrack(const ScrollbarParams& aParams) { return WidgetInfo(Widget::eScrollbarTrack, aParams); }
+    static WidgetInfo MultilineTextField(bool aParams) { return WidgetInfo(Widget::eMultilineTextField, aParams); }
+    static WidgetInfo ListBox() { return WidgetInfo(Widget::eListBox, false); }
+    static WidgetInfo SourceList(bool aParams) { return WidgetInfo(Widget::eSourceList, aParams); }
+    static WidgetInfo ActiveSourceListSelection(bool aParams) { return WidgetInfo(Widget::eActiveSourceListSelection, aParams); }
+    static WidgetInfo InactiveSourceListSelection(bool aParams) { return WidgetInfo(Widget::eInactiveSourceListSelection, aParams); }
+    static WidgetInfo TabPanel(bool aParams) { return WidgetInfo(Widget::eTabPanel, aParams); }
+    static WidgetInfo Resizer(bool aParams) { return WidgetInfo(Widget::eResizer, aParams); }
+
+    template<typename T>
+    T Params() const
+    {
+      MOZ_RELEASE_ASSERT(mVariant.is<T>());
+      return mVariant.as<T>();
+    }
+
+    enum Widget Widget() const { return mWidget; }
+
+  private:
+    template<typename T> WidgetInfo(enum Widget aWidget, const T& aParams)
+      : mVariant(aParams)
+      , mWidget(aWidget)
+    {}
+
+    mozilla::Variant<
+      mozilla::gfx::Color,
+      MenuBackgroundParams,
+      MenuIconParams,
+      MenuItemParams,
+      CheckboxOrRadioParams,
+      ButtonParams,
+      DropdownParams,
+      SpinButtonParams,
+      SegmentParams,
+      UnifiedToolbarParams,
+      TextBoxParams,
+      SearchFieldParams,
+      ProgressParams,
+      MeterParams,
+      TreeHeaderCellParams,
+      ScaleParams,
+      ScrollbarParams,
+      bool
+    > mVariant;
+
+    enum Widget mWidget;
+  };
+
   nsNativeThemeCocoa();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // The nsITheme interface.
   NS_IMETHOD DrawWidgetBackground(gfxContext* aContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2821,24 +2821,16 @@ nsNativeThemeCocoa::DrawSourceList(CGCon
   backgroundGradient =
     CGGradientCreateWithColorComponents(rgb, aIsActive ? activeGradientColors
                                                         : inactiveGradientColors, NULL, 2);
   CGContextDrawLinearGradient(cgContext, backgroundGradient, start, end, 0);
   CGGradientRelease(backgroundGradient);
   CGColorSpaceRelease(rgb);
 }
 
-static void
-DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect,
-                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType)
-{
-  DrawVibrancyBackground(cgContext, inBoxRect,
-                         VibrancyFillColor(aFrame, aThemeGeometryType), 0);
-}
-
 bool
 nsNativeThemeCocoa::IsParentScrollbarRolledOver(nsIFrame* aFrame)
 {
   nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
   return nsLookAndFeel::UseOverlayScrollbars()
     ? CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover)
     : GetContentState(scrollbarFrame, NS_THEME_NONE).HasState(NS_EVENT_STATE_HOVER);
 }
@@ -2922,92 +2914,94 @@ nsNativeThemeCocoa::DrawWidgetBackground
   CGRect bounds = CGContextGetClipBoundingBox(cgContext);
   fprintf(stderr, "    --> clip bounds: %f %f %f %f\n",
           bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
 
   //CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1);
   //CGContextFillRect(cgContext, bounds);
 #endif
 
+  Maybe<WidgetInfo> widgetInfo;
+
   EventStates eventState = GetContentState(aFrame, aWidgetType);
 
   switch (aWidgetType) {
-    case NS_THEME_DIALOG: {
+    case NS_THEME_DIALOG:
       if (IsWindowSheet(aFrame)) {
         if (VibrancyManager::SystemSupportsVibrancy()) {
           ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-          DrawVibrancyBackground(cgContext, macRect, aFrame, type);
+          widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
         } else {
-          HIThemeSetFill(kThemeBrushSheetBackgroundTransparent, NULL, cgContext, HITHEME_ORIENTATION);
-          CGContextFillRect(cgContext, macRect);
+          widgetInfo = Some(WidgetInfo::SheetBackground());
         }
       } else {
-        HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
-        CGContextFillRect(cgContext, macRect);
+        widgetInfo = Some(WidgetInfo::DialogBackground());
       }
-
-    }
       break;
 
     case NS_THEME_MENUPOPUP:
-      DrawMenuBackground(cgContext, macRect,
-                         ComputeMenuBackgroundParams(aFrame, eventState));
+      widgetInfo = Some(WidgetInfo::MenuBackground(
+        ComputeMenuBackgroundParams(aFrame, eventState)));
       break;
 
     case NS_THEME_MENUARROW:
-      DrawMenuIcon(cgContext, macRect,
-                   ComputeMenuIconParams(aFrame, eventState,
-                                         MenuIcon::eMenuArrow));
+      widgetInfo = Some(WidgetInfo::MenuIcon(
+        ComputeMenuIconParams(aFrame, eventState,
+                              MenuIcon::eMenuArrow)));
       break;
 
     case NS_THEME_MENUITEM:
     case NS_THEME_CHECKMENUITEM:
-      DrawMenuItem(cgContext, macRect,
-                   ComputeMenuItemParams(aFrame, eventState,
-                                         aWidgetType == NS_THEME_CHECKMENUITEM));
+      widgetInfo = Some(WidgetInfo::MenuItem(
+        ComputeMenuItemParams(aFrame, eventState,
+                              aWidgetType == NS_THEME_CHECKMENUITEM)));
       break;
 
     case NS_THEME_MENUSEPARATOR:
-      DrawMenuSeparator(cgContext, macRect,
-                        ComputeMenuItemParams(aFrame, eventState, false));
+      widgetInfo = 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;
-      DrawMenuIcon(cgContext, macRect,
-                   ComputeMenuIconParams(aFrame, eventState, icon));
+      widgetInfo = Some(WidgetInfo::MenuIcon(
+        ComputeMenuIconParams(aFrame, eventState, icon)));
     }
       break;
 
     case NS_THEME_TOOLTIP:
       if (VibrancyManager::SystemSupportsVibrancy()) {
-        DrawVibrancyBackground(cgContext, macRect, aFrame, ThemeGeometryTypeForWidget(aFrame, aWidgetType));
+        ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
+        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       } else {
-        SetCGContextFillColor(cgContext, kTooltipBackgroundColor);
-        CGContextFillRect(cgContext, macRect);
+        widgetInfo = Some(WidgetInfo::Tooltip());
       }
       break;
 
     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);
-      DrawCheckboxOrRadio(cgContext, isCheckbox, macRect, params);
+      if (isCheckbox) {
+        widgetInfo = Some(WidgetInfo::Checkbox(params));
+      } else {
+        widgetInfo = 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
@@ -3025,71 +3019,71 @@ 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;
-        DrawButton(cgContext, macRect, ButtonParams{params, buttonType});
+        widgetInfo = Some(WidgetInfo::Button(ButtonParams{params, buttonType}));
       } else 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;
-        DrawDropdown(cgContext, macRect, params);
+        widgetInfo = Some(WidgetInfo::Dropdown(params));
       } else if (nativeWidgetHeight > 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.
-        DrawButton(cgContext, macRect,
-                   ButtonParams{ComputeControlParams(aFrame, eventState),
-                                ButtonType::eSquareBezelPushButton});
+        widgetInfo = Some(WidgetInfo::Button(
+          ButtonParams{ComputeControlParams(aFrame, eventState),
+                       ButtonType::eSquareBezelPushButton}));
       } else {
-        DrawButton(cgContext, macRect,
-                   ButtonParams{ComputeControlParams(aFrame, eventState),
-                                ButtonType::eRoundedBezelPushButton});
+        widgetInfo = Some(WidgetInfo::Button(
+          ButtonParams{ComputeControlParams(aFrame, eventState),
+                       ButtonType::eRoundedBezelPushButton}));
       }
       break;
 
     case NS_THEME_FOCUS_OUTLINE:
-      DrawFocusOutline(cgContext, macRect);
+      widgetInfo = Some(WidgetInfo::FocusOutline());
       break;
 
     case NS_THEME_MAC_HELP_BUTTON:
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              ButtonType::eHelpButton});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                      ButtonType::eHelpButton}));
       break;
 
     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;
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              buttonType});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                    buttonType}));
     }
       break;
 
     case NS_THEME_BUTTON_BEVEL: {
       bool isDefaultButton = IsDefaultButton(aFrame);
       ButtonType buttonType =
         isDefaultButton ? ButtonType::eDefaultBevelButton
                         : ButtonType::eRegularBevelButton;
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              buttonType});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                    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()) {
@@ -3106,17 +3100,17 @@ 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);
 
-      DrawSpinButtons(cgContext, macRect, params);
+      widgetInfo = Some(WidgetInfo::SpinButtons(params));
     }
       break;
 
     case NS_THEME_SPINNER_UPBUTTON:
     case NS_THEME_SPINNER_DOWNBUTTON: {
       nsNumberControlFrame* numberControlFrame =
         nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
       if (numberControlFrame) {
@@ -3124,310 +3118,488 @@ nsNativeThemeCocoa::DrawWidgetBackground
         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) {
-          DrawSpinButton(cgContext, macRect, SpinButton::eUp, params);
+          widgetInfo = Some(WidgetInfo::SpinButtonUp(params));
         } else {
-          DrawSpinButton(cgContext, macRect, SpinButton::eDown, params);
+          widgetInfo = Some(WidgetInfo::SpinButtonDown(params));
         }
       }
     }
       break;
 
     case NS_THEME_TOOLBARBUTTON: {
       SegmentParams params =
         ComputeSegmentParams(aFrame, eventState, SegmentType::eToolbarButton);
       params.insideActiveWindow = [NativeWindowForFrame(aFrame) isMainWindow];
-      DrawSegment(cgContext, macRect, params);
+      widgetInfo = Some(WidgetInfo::Segment(params));
     }
       break;
 
-    case NS_THEME_SEPARATOR: {
-      HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive };
-      HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION);
-    }
+    case NS_THEME_SEPARATOR:
+      widgetInfo = Some(WidgetInfo::Separator());
       break;
 
     case NS_THEME_TOOLBAR: {
       NSWindow* win = NativeWindowForFrame(aFrame);
       bool isMain = [win isMainWindow];
       if (ToolbarCanBeUnified(macRect, win)) {
-        float unifiedHeight =
-          std::max([(ToolbarWindow*)win unifiedToolbarHeight],
-                   macRect.size.height);
-        DrawUnifiedToolbar(cgContext, macRect,
-                           UnifiedToolbarParams{unifiedHeight, isMain});
-        break;
+        float unifiedHeight = std::max([(ToolbarWindow*)win unifiedToolbarHeight],
+                                       macRect.size.height);
+        widgetInfo = Some(WidgetInfo::UnifiedToolbar(
+          UnifiedToolbarParams{unifiedHeight, isMain}));
+      } else {
+        widgetInfo = Some(WidgetInfo::Toolbar(isMain));
       }
-      DrawToolbar(cgContext, macRect, isMain);
     }
       break;
 
     case NS_THEME_WINDOW_TITLEBAR: {
       NSWindow* win = NativeWindowForFrame(aFrame);
       bool isMain = [win isMainWindow];
       float unifiedToolbarHeight = [win isKindOfClass:[ToolbarWindow class]] ?
         [(ToolbarWindow*)win unifiedToolbarHeight] : macRect.size.height;
-      DrawNativeTitlebar(cgContext, macRect,
-                         UnifiedToolbarParams{unifiedToolbarHeight, isMain});
+      widgetInfo = Some(WidgetInfo::NativeTitlebar(
+        UnifiedToolbarParams{unifiedToolbarHeight, isMain}));
     }
       break;
 
     case NS_THEME_STATUSBAR:
-      DrawStatusBar(cgContext, macRect, IsActive(aFrame, YES));
+      widgetInfo = Some(WidgetInfo::StatusBar(IsActive(aFrame, YES)));
       break;
 
     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;
-      DrawDropdown(cgContext, macRect, params);
+      widgetInfo = Some(WidgetInfo::Dropdown(params));
     }
       break;
 
     case NS_THEME_MENULIST_BUTTON:
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              ButtonType::eArrowButton});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                    ButtonType::eArrowButton}));
       break;
 
-    case NS_THEME_GROUPBOX: {
-      HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary };
-      HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION);
+    case NS_THEME_GROUPBOX:
+      widgetInfo = Some(WidgetInfo::GroupBox());
       break;
-    }
 
     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);
-      DrawTextBox(cgContext, macRect, TextBoxParams{isDisabled, isFocused});
+      widgetInfo = Some(WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused}));
       break;
     }
 
     case NS_THEME_SEARCHFIELD:
-      DrawSearchField(cgContext, macRect,
-                      ComputeSearchFieldParams(aFrame, eventState));
+      widgetInfo = 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!");
         }
       }
-      DrawProgress(cgContext, macRect,
-                   ComputeProgressParams(aFrame, eventState,
-                                         !IsVerticalProgress(aFrame)));
+      widgetInfo = Some(WidgetInfo::ProgressBar(
+        ComputeProgressParams(aFrame, eventState,
+                              !IsVerticalProgress(aFrame))));
       break;
     }
 
     case NS_THEME_PROGRESSBAR_VERTICAL:
-      DrawProgress(cgContext, macRect,
-                   ComputeProgressParams(aFrame, eventState, false));
+      widgetInfo = Some(WidgetInfo::ProgressBar(
+        ComputeProgressParams(aFrame, eventState, false)));
       break;
 
     case NS_THEME_METERBAR:
-      DrawMeter(cgContext, macRect, ComputeMeterParams(aFrame));
+      widgetInfo = Some(WidgetInfo::Meter(ComputeMeterParams(aFrame)));
       break;
 
     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:
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              ButtonType::eTreeTwistyPointingRight});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                     ButtonType::eTreeTwistyPointingRight}));
       break;
 
     case NS_THEME_TREETWISTYOPEN:
-      DrawButton(cgContext, macRect,
-                 ButtonParams{ComputeControlParams(aFrame, eventState),
-                              ButtonType::eTreeTwistyPointingDown});
+      widgetInfo = Some(WidgetInfo::Button(
+        ButtonParams{ComputeControlParams(aFrame, eventState),
+                     ButtonType::eTreeTwistyPointingDown}));
       break;
 
     case NS_THEME_TREEHEADERCELL:
-      DrawTreeHeaderCell(cgContext, macRect,
-                         ComputeTreeHeaderCellParams(aFrame, eventState));
+      widgetInfo = Some(WidgetInfo::TreeHeaderCell(
+        ComputeTreeHeaderCellParams(aFrame, eventState)));
       break;
 
     case NS_THEME_TREEITEM:
     case NS_THEME_TREEVIEW:
-      // HIThemeSetFill is not available on 10.3
-      // HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION);
-      CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
-      CGContextFillRect(cgContext, macRect);
+      widgetInfo = Some(WidgetInfo::ColorFill(Color(1.0, 1.0, 1.0, 1.0)));
       break;
 
     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:
-      DrawScale(cgContext, macRect,
-                ComputeXULScaleParams(aFrame, eventState,
-                                      aWidgetType == NS_THEME_SCALE_HORIZONTAL));
+      widgetInfo = 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) {
-        DrawScale(cgContext, macRect, *params);
+        widgetInfo = 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:
-      DrawScrollbarThumb(cgContext, macRect,
+      widgetInfo = Some(WidgetInfo::ScrollbarThumb(
         ComputeScrollbarParams(
-          aFrame, aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL));
+          aFrame, aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL)));
       break;
 
     case NS_THEME_SCROLLBARBUTTON_UP:
     case NS_THEME_SCROLLBARBUTTON_LEFT:
-#if SCROLLBARS_VISUAL_DEBUG
-      CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6);
-      CGContextFillRect(cgContext, macRect);
-#endif
-    break;
     case NS_THEME_SCROLLBARBUTTON_DOWN:
     case NS_THEME_SCROLLBARBUTTON_RIGHT:
-#if SCROLLBARS_VISUAL_DEBUG
-      CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6);
-      CGContextFillRect(cgContext, macRect);
-#endif
-    break;
+      break;
+
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
-      DrawScrollbarTrack(cgContext, macRect,
+      widgetInfo = Some(WidgetInfo::ScrollbarTrack(
         ComputeScrollbarParams(
-          aFrame, aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL));
+          aFrame, aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL)));
       break;
 
     case NS_THEME_TEXTFIELD_MULTILINE:
-      DrawMultilineTextField(cgContext, macRect,
-                             eventState.HasState(NS_EVENT_STATE_FOCUS));
+      widgetInfo = Some(WidgetInfo::MultilineTextField(
+        eventState.HasState(NS_EVENT_STATE_FOCUS)));
       break;
 
-    case NS_THEME_LISTBOX: {
-      // We have to draw this by hand because kHIThemeFrameListBox drawing
-      // is buggy on 10.5, see bug 579259.
-      CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
-      CGContextFillRect(cgContext, macRect);
-
-      float x = macRect.origin.x, y = macRect.origin.y;
-      float w = macRect.size.width, h = macRect.size.height;
-      SetCGContextFillColor(cgContext, kListboxTopBorderColor);
-      CGContextFillRect(cgContext, CGRectMake(x, y, w, 1));
-      SetCGContextFillColor(cgContext, kListBoxSidesAndBottomBorderColor);
-      CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1));
-      CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1));
-      CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1));
-    }
+    case NS_THEME_LISTBOX:
+      widgetInfo = Some(WidgetInfo::ListBox());
       break;
 
     case NS_THEME_MAC_SOURCE_LIST: {
       if (VibrancyManager::SystemSupportsVibrancy()) {
         ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType);
-        DrawVibrancyBackground(cgContext, macRect, aFrame, type);
+        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       } else {
-        DrawSourceList(cgContext, macRect, FrameIsInActiveWindow(aFrame));
+        widgetInfo = 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);
-        DrawVibrancyBackground(cgContext, macRect, aFrame, type);
+        widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       } else {
-        BOOL isActiveSelection =
-          aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION;
-        RenderWithCoreUI(macRect, cgContext,
-          [NSDictionary dictionaryWithObjectsAndKeys:
-            [NSNumber numberWithBool:isActiveSelection], @"focus",
-            [NSNumber numberWithBool:YES], @"is.flipped",
-            @"kCUIVariantGradientSideBarSelection", @"kCUIVariantKey",
-            (FrameIsInActiveWindow(aFrame) ? @"normal" : @"inactive"), @"state",
-            @"gradient", @"widget",
-            nil]);
+        bool isInActiveWindow = FrameIsInActiveWindow(aFrame);
+        if (aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION) {
+          widgetInfo = Some(WidgetInfo::ActiveSourceListSelection(isInActiveWindow));
+        } else {
+          widgetInfo = Some(WidgetInfo::InactiveSourceListSelection(isInActiveWindow));
+        }
       }
     }
       break;
 
     case NS_THEME_TAB: {
       SegmentParams params =
         ComputeSegmentParams(aFrame, eventState, SegmentType::eTab);
       params.pressed = params.pressed && !params.selected;
-      DrawSegment(cgContext, macRect, params);
+      widgetInfo = Some(WidgetInfo::Segment(params));
     }
       break;
 
     case NS_THEME_TABPANELS:
-      DrawTabPanel(cgContext, macRect, FrameIsInActiveWindow(aFrame));
+      widgetInfo = Some(WidgetInfo::TabPanel(FrameIsInActiveWindow(aFrame)));
       break;
 
     case NS_THEME_RESIZER:
-      DrawResizer(cgContext, macRect, IsFrameRTL(aFrame));
+      widgetInfo = Some(WidgetInfo::Resizer(IsFrameRTL(aFrame)));
       break;
 
     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);
-      DrawVibrancyBackground(cgContext, macRect, aFrame, type);
+      widgetInfo = Some(WidgetInfo::ColorFill(VibrancyFillColor(aFrame, type)));
       break;
     }
   }
 
+  if (widgetInfo) {
+    switch (widgetInfo->Widget()) {
+      case Widget::eColorFill: {
+        Color params = widgetInfo->Params<Color>();
+        SetCGContextFillColor(cgContext, params);
+        CGContextFillRect(cgContext, macRect);
+        break;
+      }
+      case Widget::eSheetBackground: {
+        HIThemeSetFill(kThemeBrushSheetBackgroundTransparent, NULL, cgContext, HITHEME_ORIENTATION);
+        CGContextFillRect(cgContext, macRect);
+        break;
+      }
+      case Widget::eDialogBackground: {
+        HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
+        CGContextFillRect(cgContext, macRect);
+        break;
+      }
+      case Widget::eMenuBackground: {
+        MenuBackgroundParams params = widgetInfo->Params<MenuBackgroundParams>();
+        DrawMenuBackground(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eMenuIcon: {
+        MenuIconParams params = widgetInfo->Params<MenuIconParams>();
+        DrawMenuIcon(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eMenuItem: {
+        MenuItemParams params = widgetInfo->Params<MenuItemParams>();
+        DrawMenuItem(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eMenuSeparator: {
+        MenuItemParams params = widgetInfo->Params<MenuItemParams>();
+        DrawMenuSeparator(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eTooltip: {
+        SetCGContextFillColor(cgContext, kTooltipBackgroundColor);
+        CGContextFillRect(cgContext, macRect);
+        break;
+      }
+      case Widget::eCheckbox: {
+        CheckboxOrRadioParams params = widgetInfo->Params<CheckboxOrRadioParams>();
+        DrawCheckboxOrRadio(cgContext, true, macRect, params);
+        break;
+      }
+      case Widget::eRadio: {
+        CheckboxOrRadioParams params = widgetInfo->Params<CheckboxOrRadioParams>();
+        DrawCheckboxOrRadio(cgContext, false, macRect, params);
+        break;
+      }
+      case Widget::eButton: {
+        ButtonParams params = widgetInfo->Params<ButtonParams>();
+        DrawButton(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eDropdown: {
+        DropdownParams params = widgetInfo->Params<DropdownParams>();
+        DrawDropdown(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eFocusOutline: {
+        DrawFocusOutline(cgContext, macRect);
+        break;
+      }
+      case Widget::eSpinButtons: {
+        SpinButtonParams params = widgetInfo->Params<SpinButtonParams>();
+        DrawSpinButtons(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eSpinButtonUp: {
+        SpinButtonParams params = widgetInfo->Params<SpinButtonParams>();
+        DrawSpinButton(cgContext, macRect, SpinButton::eUp, params);
+        break;
+      }
+      case Widget::eSpinButtonDown: {
+        SpinButtonParams params = widgetInfo->Params<SpinButtonParams>();
+        DrawSpinButton(cgContext, macRect, SpinButton::eDown, params);
+        break;
+      }
+      case Widget::eSegment: {
+        SegmentParams params = widgetInfo->Params<SegmentParams>();
+        DrawSegment(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eSeparator: {
+        HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive };
+        HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION);
+        break;
+      }
+      case Widget::eUnifiedToolbar: {
+        UnifiedToolbarParams params = widgetInfo->Params<UnifiedToolbarParams>();
+        DrawUnifiedToolbar(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eToolbar: {
+        bool isMain = widgetInfo->Params<bool>();
+        DrawToolbar(cgContext, macRect, isMain);
+        break;
+      }
+      case Widget::eNativeTitlebar: {
+        UnifiedToolbarParams params = widgetInfo->Params<UnifiedToolbarParams>();
+        DrawNativeTitlebar(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eStatusBar: {
+        bool isMain = widgetInfo->Params<bool>();
+        DrawStatusBar(cgContext, macRect, isMain);
+        break;
+      }
+      case Widget::eGroupBox: {
+        HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary };
+        HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION);
+        break;
+      }
+      case Widget::eTextBox: {
+        TextBoxParams params = widgetInfo->Params<TextBoxParams>();
+        DrawTextBox(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eSearchField: {
+        SearchFieldParams params = widgetInfo->Params<SearchFieldParams>();
+        DrawSearchField(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eProgressBar: {
+        ProgressParams params = widgetInfo->Params<ProgressParams>();
+        DrawProgress(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eMeter: {
+        MeterParams params = widgetInfo->Params<MeterParams>();
+        DrawMeter(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eTreeHeaderCell: {
+        TreeHeaderCellParams params = widgetInfo->Params<TreeHeaderCellParams>();
+        DrawTreeHeaderCell(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eScale: {
+        ScaleParams params = widgetInfo->Params<ScaleParams>();
+        DrawScale(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eScrollbarThumb: {
+        ScrollbarParams params = widgetInfo->Params<ScrollbarParams>();
+        DrawScrollbarThumb(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eScrollbarTrack: {
+        ScrollbarParams params = widgetInfo->Params<ScrollbarParams>();
+        DrawScrollbarTrack(cgContext, macRect, params);
+        break;
+      }
+      case Widget::eMultilineTextField: {
+        bool isFocused = widgetInfo->Params<bool>();
+        DrawMultilineTextField(cgContext, macRect, isFocused);
+        break;
+      }
+      case Widget::eListBox: {
+        // We have to draw this by hand because kHIThemeFrameListBox drawing
+        // is buggy on 10.5, see bug 579259.
+        CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
+        CGContextFillRect(cgContext, macRect);
+
+        float x = macRect.origin.x, y = macRect.origin.y;
+        float w = macRect.size.width, h = macRect.size.height;
+        SetCGContextFillColor(cgContext, kListboxTopBorderColor);
+        CGContextFillRect(cgContext, CGRectMake(x, y, w, 1));
+        SetCGContextFillColor(cgContext, kListBoxSidesAndBottomBorderColor);
+        CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1));
+        CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1));
+        CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1));
+        break;
+      }
+      case Widget::eSourceList: {
+        bool isInActiveWindow = widgetInfo->Params<bool>();
+        DrawSourceList(cgContext, macRect, isInActiveWindow);
+        break;
+      }
+      case Widget::eActiveSourceListSelection:
+      case Widget::eInactiveSourceListSelection: {
+        bool isInActiveWindow = widgetInfo->Params<bool>();
+        BOOL isActiveSelection =
+          widgetInfo->Widget() == Widget::eActiveSourceListSelection;
+        RenderWithCoreUI(macRect, cgContext,
+          [NSDictionary dictionaryWithObjectsAndKeys:
+            [NSNumber numberWithBool:isActiveSelection], @"focus",
+            [NSNumber numberWithBool:YES], @"is.flipped",
+            @"kCUIVariantGradientSideBarSelection", @"kCUIVariantKey",
+            (isInActiveWindow ? @"normal" : @"inactive"), @"state",
+            @"gradient", @"widget",
+            nil]);
+        break;
+      }
+      case Widget::eTabPanel: {
+        bool isInsideActiveWindow = widgetInfo->Params<bool>();
+        DrawTabPanel(cgContext, macRect, isInsideActiveWindow);
+        break;
+      }
+      case Widget::eResizer: {
+        bool isRTL = widgetInfo->Params<bool>();
+        DrawResizer(cgContext, macRect, isRTL);
+        break;
+      }
+    }
+  }
+
   if (hidpi) {
     // Reset the base CTM.
     CGContextSetBaseCTM(cgContext, CGAffineTransformIdentity);
   }
 
   nativeDrawing.EndNativeDrawing();
 
   return NS_OK;