widget/windows/nsNativeThemeWin.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/windows/nsNativeThemeWin.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4051 @@
     1.4 +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsNativeThemeWin.h"
    1.10 +#include "mozilla/EventStates.h"
    1.11 +#include "mozilla/WindowsVersion.h"
    1.12 +#include "nsRenderingContext.h"
    1.13 +#include "nsRect.h"
    1.14 +#include "nsSize.h"
    1.15 +#include "nsTransform2D.h"
    1.16 +#include "nsThemeConstants.h"
    1.17 +#include "nsIPresShell.h"
    1.18 +#include "nsPresContext.h"
    1.19 +#include "nsIContent.h"
    1.20 +#include "nsIFrame.h"
    1.21 +#include "nsNameSpaceManager.h"
    1.22 +#include "nsIDOMHTMLInputElement.h"
    1.23 +#include "nsLookAndFeel.h"
    1.24 +#include "nsMenuFrame.h"
    1.25 +#include "nsGkAtoms.h"
    1.26 +#include <malloc.h>
    1.27 +#include "nsWindow.h"
    1.28 +#include "nsIComboboxControlFrame.h"
    1.29 +#include "prinrval.h"
    1.30 +#include "WinUtils.h"
    1.31 +
    1.32 +#include "gfxPlatform.h"
    1.33 +#include "gfxContext.h"
    1.34 +#include "gfxWindowsPlatform.h"
    1.35 +#include "gfxWindowsSurface.h"
    1.36 +#include "gfxWindowsNativeDrawing.h"
    1.37 +
    1.38 +#include "nsUXThemeData.h"
    1.39 +#include "nsUXThemeConstants.h"
    1.40 +#include <algorithm>
    1.41 +
    1.42 +using mozilla::IsVistaOrLater;
    1.43 +using namespace mozilla;
    1.44 +using namespace mozilla::widget;
    1.45 +
    1.46 +#ifdef PR_LOGGING
    1.47 +extern PRLogModuleInfo* gWindowsLog;
    1.48 +#endif
    1.49 +
    1.50 +NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeWin, nsNativeTheme, nsITheme)
    1.51 +
    1.52 +nsNativeThemeWin::nsNativeThemeWin() :
    1.53 +  mProgressDeterminateTimeStamp(TimeStamp::Now()),
    1.54 +  mProgressIndeterminateTimeStamp(TimeStamp::Now())
    1.55 +{
    1.56 +  // If there is a relevant change in forms.css for windows platform,
    1.57 +  // static widget style variables (e.g. sButtonBorderSize) should be 
    1.58 +  // reinitialized here.
    1.59 +}
    1.60 +
    1.61 +nsNativeThemeWin::~nsNativeThemeWin()
    1.62 +{
    1.63 +  nsUXThemeData::Invalidate();
    1.64 +}
    1.65 +
    1.66 +static int32_t
    1.67 +GetTopLevelWindowActiveState(nsIFrame *aFrame)
    1.68 +{
    1.69 +  // Get the widget. nsIFrame's GetNearestWidget walks up the view chain
    1.70 +  // until it finds a real window.
    1.71 +  nsIWidget* widget = aFrame->GetNearestWidget();
    1.72 +  nsWindowBase * window = static_cast<nsWindowBase*>(widget);
    1.73 +  if (!window)
    1.74 +    return mozilla::widget::themeconst::FS_INACTIVE;
    1.75 +  if (widget && !window->IsTopLevelWidget() &&
    1.76 +      !(window = window->GetParentWindowBase(false)))
    1.77 +    return mozilla::widget::themeconst::FS_INACTIVE;
    1.78 +
    1.79 +  if (window->GetWindowHandle() == ::GetActiveWindow())
    1.80 +    return mozilla::widget::themeconst::FS_ACTIVE;
    1.81 +  return mozilla::widget::themeconst::FS_INACTIVE;
    1.82 +}
    1.83 +
    1.84 +static int32_t
    1.85 +GetWindowFrameButtonState(nsIFrame* aFrame, EventStates eventState)
    1.86 +{
    1.87 +  if (GetTopLevelWindowActiveState(aFrame) ==
    1.88 +      mozilla::widget::themeconst::FS_INACTIVE) {
    1.89 +    if (eventState.HasState(NS_EVENT_STATE_HOVER))
    1.90 +      return mozilla::widget::themeconst::BS_HOT;
    1.91 +    return mozilla::widget::themeconst::BS_INACTIVE;
    1.92 +  }
    1.93 +
    1.94 +  if (eventState.HasState(NS_EVENT_STATE_HOVER)) {
    1.95 +    if (eventState.HasState(NS_EVENT_STATE_ACTIVE))
    1.96 +      return mozilla::widget::themeconst::BS_PUSHED;
    1.97 +    return mozilla::widget::themeconst::BS_HOT;
    1.98 +  }
    1.99 +  return mozilla::widget::themeconst::BS_NORMAL;
   1.100 +}
   1.101 +
   1.102 +static int32_t
   1.103 +GetClassicWindowFrameButtonState(EventStates eventState)
   1.104 +{
   1.105 +  if (eventState.HasState(NS_EVENT_STATE_ACTIVE) &&
   1.106 +      eventState.HasState(NS_EVENT_STATE_HOVER))
   1.107 +    return DFCS_BUTTONPUSH|DFCS_PUSHED;
   1.108 +  return DFCS_BUTTONPUSH;
   1.109 +}
   1.110 +
   1.111 +static bool
   1.112 +IsTopLevelMenu(nsIFrame *aFrame)
   1.113 +{
   1.114 +  bool isTopLevel(false);
   1.115 +  nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
   1.116 +  if (menuFrame) {
   1.117 +    isTopLevel = menuFrame->IsOnMenuBar();
   1.118 +  }
   1.119 +  return isTopLevel;
   1.120 +}
   1.121 +
   1.122 +static MARGINS
   1.123 +GetCheckboxMargins(HANDLE theme, HDC hdc)
   1.124 +{
   1.125 +    MARGINS checkboxContent = {0};
   1.126 +    GetThemeMargins(theme, hdc, MENU_POPUPCHECK, MCB_NORMAL,
   1.127 +                    TMT_CONTENTMARGINS, nullptr, &checkboxContent);
   1.128 +    return checkboxContent;
   1.129 +}
   1.130 +
   1.131 +static SIZE
   1.132 +GetCheckboxBGSize(HANDLE theme, HDC hdc)
   1.133 +{
   1.134 +    SIZE checkboxSize;
   1.135 +    GetThemePartSize(theme, hdc, MENU_POPUPCHECK, MC_CHECKMARKNORMAL,
   1.136 +                     nullptr, TS_TRUE, &checkboxSize);
   1.137 +
   1.138 +    MARGINS checkboxMargins = GetCheckboxMargins(theme, hdc);
   1.139 +
   1.140 +    int leftMargin = checkboxMargins.cxLeftWidth;
   1.141 +    int rightMargin = checkboxMargins.cxRightWidth;
   1.142 +    int topMargin = checkboxMargins.cyTopHeight;
   1.143 +    int bottomMargin = checkboxMargins.cyBottomHeight;
   1.144 +
   1.145 +    int width = leftMargin + checkboxSize.cx + rightMargin;
   1.146 +    int height = topMargin + checkboxSize.cy + bottomMargin;
   1.147 +    SIZE ret;
   1.148 +    ret.cx = width;
   1.149 +    ret.cy = height;
   1.150 +    return ret;
   1.151 +}
   1.152 +
   1.153 +static SIZE
   1.154 +GetCheckboxBGBounds(HANDLE theme, HDC hdc)
   1.155 +{
   1.156 +    MARGINS checkboxBGSizing = {0};
   1.157 +    MARGINS checkboxBGContent = {0};
   1.158 +    GetThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL,
   1.159 +                    TMT_SIZINGMARGINS, nullptr, &checkboxBGSizing);
   1.160 +    GetThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL,
   1.161 +                    TMT_CONTENTMARGINS, nullptr, &checkboxBGContent);
   1.162 +
   1.163 +#define posdx(d) ((d) > 0 ? d : 0)
   1.164 +
   1.165 +    int dx = posdx(checkboxBGContent.cxRightWidth -
   1.166 +                   checkboxBGSizing.cxRightWidth) +
   1.167 +             posdx(checkboxBGContent.cxLeftWidth -
   1.168 +                   checkboxBGSizing.cxLeftWidth);
   1.169 +    int dy = posdx(checkboxBGContent.cyTopHeight -
   1.170 +                   checkboxBGSizing.cyTopHeight) +
   1.171 +             posdx(checkboxBGContent.cyBottomHeight -
   1.172 +                   checkboxBGSizing.cyBottomHeight);
   1.173 +
   1.174 +#undef posdx
   1.175 +
   1.176 +    SIZE ret(GetCheckboxBGSize(theme, hdc));
   1.177 +    ret.cx += dx;
   1.178 +    ret.cy += dy;
   1.179 +    return ret;
   1.180 +}
   1.181 +
   1.182 +static SIZE
   1.183 +GetGutterSize(HANDLE theme, HDC hdc)
   1.184 +{
   1.185 +    SIZE gutterSize;
   1.186 +    GetThemePartSize(theme, hdc, MENU_POPUPGUTTER, 0, nullptr, TS_TRUE, &gutterSize);
   1.187 +
   1.188 +    SIZE checkboxBGSize(GetCheckboxBGBounds(theme, hdc));
   1.189 +
   1.190 +    SIZE itemSize;
   1.191 +    GetThemePartSize(theme, hdc, MENU_POPUPITEM, MPI_NORMAL, nullptr, TS_TRUE, &itemSize);
   1.192 +
   1.193 +    // Figure out how big the menuitem's icon will be (if present) at current DPI
   1.194 +    double scaleFactor = nsIWidget::DefaultScaleOverride();
   1.195 +    if (scaleFactor <= 0.0) {
   1.196 +      scaleFactor = gfxWindowsPlatform::GetPlatform()->GetDPIScale();
   1.197 +    }
   1.198 +    int iconDevicePixels = NSToIntRound(16 * scaleFactor);
   1.199 +    SIZE iconSize = {
   1.200 +      iconDevicePixels, iconDevicePixels
   1.201 +    };
   1.202 +    // Not really sure what margins should be used here, but this seems to work in practice...
   1.203 +    MARGINS margins = {0};
   1.204 +    GetThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL,
   1.205 +                    TMT_CONTENTMARGINS, nullptr, &margins);
   1.206 +    iconSize.cx += margins.cxLeftWidth + margins.cxRightWidth;
   1.207 +    iconSize.cy += margins.cyTopHeight + margins.cyBottomHeight;
   1.208 +
   1.209 +    int width = std::max(itemSize.cx, std::max(iconSize.cx, checkboxBGSize.cx) + gutterSize.cx);
   1.210 +    int height = std::max(itemSize.cy, std::max(iconSize.cy, checkboxBGSize.cy));
   1.211 +
   1.212 +    SIZE ret;
   1.213 +    ret.cx = width;
   1.214 +    ret.cy = height;
   1.215 +    return ret;
   1.216 +}
   1.217 +
   1.218 +/* DrawThemeBGRTLAware - render a theme part based on rtl state.
   1.219 + * Some widgets are not direction-neutral and need to be drawn reversed for
   1.220 + * RTL.  Windows provides a way to do this with SetLayout, but this reverses
   1.221 + * the entire drawing area of a given device context, which means that its
   1.222 + * use will also affect the positioning of the widget.  There are two ways
   1.223 + * to work around this:
   1.224 + *
   1.225 + * Option 1: Alter the position of the rect that we send so that we cancel
   1.226 + *           out the positioning effects of SetLayout
   1.227 + * Option 2: Create a memory DC with the widgetRect's dimensions, draw onto
   1.228 + *           that, and then transfer the results back to our DC
   1.229 + *
   1.230 + * This function tries to implement option 1, under the assumption that the
   1.231 + * correct way to reverse the effects of SetLayout is to translate the rect
   1.232 + * such that the offset from the DC bitmap's left edge to the old rect's
   1.233 + * left edge is equal to the offset from the DC bitmap's right edge to the
   1.234 + * new rect's right edge.  In other words,
   1.235 + * (oldRect.left + vpOrg.x) == ((dcBMP.width - vpOrg.x) - newRect.right)
   1.236 + */
   1.237 +static HRESULT
   1.238 +DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, int aState,
   1.239 +                    const RECT *aWidgetRect, const RECT *aClipRect,
   1.240 +                    bool aIsRtl)
   1.241 +{
   1.242 +  NS_ASSERTION(aTheme, "Bad theme handle.");
   1.243 +  NS_ASSERTION(aHdc, "Bad hdc.");
   1.244 +  NS_ASSERTION(aWidgetRect, "Bad rect.");
   1.245 +  NS_ASSERTION(aClipRect, "Bad clip rect.");
   1.246 +
   1.247 +  if (!aIsRtl) {
   1.248 +    return DrawThemeBackground(aTheme, aHdc, aPart, aState,
   1.249 +                               aWidgetRect, aClipRect);
   1.250 +  }
   1.251 +
   1.252 +  HGDIOBJ hObj = GetCurrentObject(aHdc, OBJ_BITMAP);
   1.253 +  BITMAP bitmap;
   1.254 +  POINT vpOrg;
   1.255 +
   1.256 +  if (hObj && GetObject(hObj, sizeof(bitmap), &bitmap) &&
   1.257 +      GetViewportOrgEx(aHdc, &vpOrg)) {
   1.258 +    RECT newWRect(*aWidgetRect);
   1.259 +    newWRect.left = bitmap.bmWidth - (aWidgetRect->right + 2*vpOrg.x);
   1.260 +    newWRect.right = bitmap.bmWidth - (aWidgetRect->left + 2*vpOrg.x);
   1.261 +
   1.262 +    RECT newCRect;
   1.263 +    RECT *newCRectPtr = nullptr;
   1.264 +
   1.265 +    if (aClipRect) {
   1.266 +      newCRect.top = aClipRect->top;
   1.267 +      newCRect.bottom = aClipRect->bottom;
   1.268 +      newCRect.left = bitmap.bmWidth - (aClipRect->right + 2*vpOrg.x);
   1.269 +      newCRect.right = bitmap.bmWidth - (aClipRect->left + 2*vpOrg.x);
   1.270 +      newCRectPtr = &newCRect;
   1.271 +    }
   1.272 +
   1.273 +    SetLayout(aHdc, LAYOUT_RTL);
   1.274 +    HRESULT hr = DrawThemeBackground(aTheme, aHdc, aPart, aState, &newWRect,
   1.275 +                                     newCRectPtr);
   1.276 +    SetLayout(aHdc, 0);
   1.277 +    if (SUCCEEDED(hr)) {
   1.278 +      return hr;
   1.279 +    }
   1.280 +  }
   1.281 +  return DrawThemeBackground(aTheme, aHdc, aPart, aState,
   1.282 +                             aWidgetRect, aClipRect);
   1.283 +}
   1.284 +
   1.285 +/*
   1.286 + *  Caption button padding data - 'hot' button padding.
   1.287 + *  These areas are considered hot, in that they activate
   1.288 + *  a button when hovered or clicked. The button graphic
   1.289 + *  is drawn inside the padding border. Unrecognized themes
   1.290 + *  are treated as their recognized counterparts for now.
   1.291 + *                       left      top    right   bottom
   1.292 + *  classic min             1        2        0        1
   1.293 + *  classic max             0        2        1        1
   1.294 + *  classic close           1        2        2        1
   1.295 + *
   1.296 + *  aero basic min          1        2        0        2
   1.297 + *  aero basic max          0        2        1        2
   1.298 + *  aero basic close        1        2        1        2
   1.299 + *
   1.300 + *  xp theme min            0        2        0        2
   1.301 + *  xp theme max            0        2        1        2
   1.302 + *  xp theme close          1        2        2        2
   1.303 + *
   1.304 + *  'cold' button padding - generic button padding, should
   1.305 + *  be handled in css.
   1.306 + *                       left      top    right   bottom
   1.307 + *  classic min             0        0        0        0
   1.308 + *  classic max             0        0        0        0
   1.309 + *  classic close           0        0        0        0
   1.310 + *
   1.311 + *  aero basic min          0        0        1        0
   1.312 + *  aero basic max          1        0        0        0
   1.313 + *  aero basic close        0        0        0        0
   1.314 + *
   1.315 + *  xp theme min            0        0        1        0
   1.316 + *  xp theme max            1        0        0        0
   1.317 + *  xp theme close          0        0        0        0
   1.318 + */
   1.319 +
   1.320 +enum CaptionDesktopTheme {
   1.321 +  CAPTION_CLASSIC = 0,
   1.322 +  CAPTION_BASIC,
   1.323 +  CAPTION_XPTHEME,
   1.324 +};
   1.325 +
   1.326 +enum CaptionButton {
   1.327 +  CAPTIONBUTTON_MINIMIZE = 0,
   1.328 +  CAPTIONBUTTON_RESTORE,
   1.329 +  CAPTIONBUTTON_CLOSE,
   1.330 +};
   1.331 +
   1.332 +struct CaptionButtonPadding {
   1.333 +  RECT hotPadding[3];
   1.334 +};
   1.335 +
   1.336 +// RECT: left, top, right, bottom
   1.337 +static CaptionButtonPadding buttonData[3] = {
   1.338 +  { 
   1.339 +    { { 1, 2, 0, 1 }, { 0, 2, 1, 1 }, { 1, 2, 2, 1 } }
   1.340 +  },
   1.341 +  { 
   1.342 +    { { 1, 2, 0, 2 }, { 0, 2, 1, 2 }, { 1, 2, 2, 2 } }
   1.343 +  },
   1.344 +  { 
   1.345 +    { { 0, 2, 0, 2 }, { 0, 2, 1, 2 }, { 1, 2, 2, 2 } }
   1.346 +  }
   1.347 +};
   1.348 +
   1.349 +// Adds "hot" caption button padding to minimum widget size.
   1.350 +static void
   1.351 +AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
   1.352 +  if (!aSize)
   1.353 +    return;
   1.354 +  RECT offset;
   1.355 +  if (!IsAppThemed())
   1.356 +    offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
   1.357 +  else if (!IsVistaOrLater())
   1.358 +    offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   1.359 +  else
   1.360 +    offset = buttonData[CAPTION_BASIC].hotPadding[button];
   1.361 +  aSize->width += offset.left + offset.right;
   1.362 +  aSize->height += offset.top + offset.bottom;
   1.363 +}
   1.364 +
   1.365 +// If we've added padding to the minimum widget size, offset
   1.366 +// the area we draw into to compensate.
   1.367 +static void
   1.368 +OffsetBackgroundRect(RECT& rect, CaptionButton button) {
   1.369 +  RECT offset;
   1.370 +  if (!IsAppThemed())
   1.371 +    offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
   1.372 +  else if (!IsVistaOrLater())
   1.373 +    offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   1.374 +  else
   1.375 +    offset = buttonData[CAPTION_BASIC].hotPadding[button];
   1.376 +  rect.left += offset.left;
   1.377 +  rect.top += offset.top;
   1.378 +  rect.right -= offset.right;
   1.379 +  rect.bottom -= offset.bottom;
   1.380 +}
   1.381 +
   1.382 +/*
   1.383 + * Notes on progress track and meter part constants:
   1.384 + * xp and up:
   1.385 + * PP_BAR(_VERT)            - base progress track
   1.386 + * PP_TRANSPARENTBAR(_VERT) - transparent progress track. this only works if
   1.387 + *                            the underlying surface supports alpha. otherwise
   1.388 + *                            theme lib's DrawThemeBackground falls back on
   1.389 + *                            opaque PP_BAR. we currently don't use this.
   1.390 + * PP_CHUNK(_VERT)          - xp progress meter. this does not draw an xp style
   1.391 + *                            progress w/chunks, it draws fill using the chunk
   1.392 + *                            graphic.
   1.393 + * vista and up:
   1.394 + * PP_FILL(_VERT)           - progress meter. these have four states/colors.
   1.395 + * PP_PULSEOVERLAY(_VERT)   - white reflection - an overlay, not sure what this
   1.396 + *                            is used for.
   1.397 + * PP_MOVEOVERLAY(_VERT)    - green pulse - the pulse effect overlay on
   1.398 + *                            determined progress bars. we also use this for
   1.399 + *                            indeterminate chunk.
   1.400 + *
   1.401 + * Notes on state constants:
   1.402 + * PBBS_NORMAL               - green progress
   1.403 + * PBBVS_PARTIAL/PBFVS_ERROR - red error progress
   1.404 + * PBFS_PAUSED               - yellow paused progress
   1.405 + *
   1.406 + * There is no common controls style indeterminate part on vista and up.
   1.407 + */
   1.408 +
   1.409 +/*
   1.410 + * Progress bar related constants. These values are found by experimenting and
   1.411 + * comparing against native widgets used by the system. They are very unlikely
   1.412 + * exact but try to not be too wrong.
   1.413 + */
   1.414 +// The amount of time we animate progress meters parts across the frame.
   1.415 +static const double kProgressDeterminateTimeSpan = 3.0;
   1.416 +static const double kProgressIndeterminateTimeSpan = 5.0;
   1.417 +// The width of the overlay used to animate the horizontal progress bar (Vista and later).
   1.418 +static const int32_t kProgressHorizontalVistaOverlaySize = 120;
   1.419 +// The width of the overlay used for the horizontal indeterminate progress bars on XP.
   1.420 +static const int32_t kProgressHorizontalXPOverlaySize = 55;
   1.421 +// The height of the overlay used to animate the vertical progress bar (Vista and later).
   1.422 +static const int32_t kProgressVerticalOverlaySize = 45;
   1.423 +// The height of the overlay used for the vertical indeterminate progress bar (Vista and later).
   1.424 +static const int32_t kProgressVerticalIndeterminateOverlaySize = 60;
   1.425 +// The width of the overlay used to animate the indeterminate progress bar (Windows Classic).
   1.426 +static const int32_t kProgressClassicOverlaySize = 40;
   1.427 +
   1.428 +/*
   1.429 + * GetProgressOverlayStyle - returns the proper overlay part for themed
   1.430 + * progress bars based on os and orientation.
   1.431 + */
   1.432 +static int32_t
   1.433 +GetProgressOverlayStyle(bool aIsVertical)
   1.434 +{ 
   1.435 +  if (aIsVertical) {
   1.436 +    if (IsVistaOrLater()) {
   1.437 +      return PP_MOVEOVERLAYVERT;
   1.438 +    }
   1.439 +    return PP_CHUNKVERT;
   1.440 +  } else {
   1.441 +    if (IsVistaOrLater()) {
   1.442 +      return PP_MOVEOVERLAY;
   1.443 +    }
   1.444 +    return PP_CHUNK;
   1.445 +  }
   1.446 +}
   1.447 +
   1.448 +/*
   1.449 + * GetProgressOverlaySize - returns the minimum width or height for themed
   1.450 + * progress bar overlays. This includes the width of indeterminate chunks
   1.451 + * and vista pulse overlays.
   1.452 + */
   1.453 +static int32_t
   1.454 +GetProgressOverlaySize(bool aIsVertical, bool aIsIndeterminate)
   1.455 +{
   1.456 +  if (IsVistaOrLater()) {
   1.457 +    if (aIsVertical) {
   1.458 +      return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize
   1.459 +                              : kProgressVerticalOverlaySize;
   1.460 +    }
   1.461 +    return kProgressHorizontalVistaOverlaySize;
   1.462 +  }
   1.463 +  return kProgressHorizontalXPOverlaySize;
   1.464 +}
   1.465 +
   1.466 +/*
   1.467 + * IsProgressMeterFilled - Determines if a progress meter is at 100% fill based
   1.468 + * on a comparison of the current value and maximum.
   1.469 + */
   1.470 +static bool
   1.471 +IsProgressMeterFilled(nsIFrame* aFrame)
   1.472 +{
   1.473 +  NS_ENSURE_TRUE(aFrame, false);
   1.474 +  nsIFrame* parentFrame = aFrame->GetParent();
   1.475 +  NS_ENSURE_TRUE(parentFrame, false);
   1.476 +  return nsNativeTheme::GetProgressValue(parentFrame) ==
   1.477 +         nsNativeTheme::GetProgressMaxValue(parentFrame);
   1.478 +}
   1.479 +
   1.480 +/*
   1.481 + * CalculateProgressOverlayRect - returns the padded overlay animation rect
   1.482 + * used in rendering progress bars. Resulting rects are used in rendering
   1.483 + * vista+ pulse overlays and indeterminate progress meters. Graphics should
   1.484 + * be rendered at the origin.
   1.485 + */
   1.486 +RECT
   1.487 +nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame* aFrame,
   1.488 +                                               RECT* aWidgetRect,
   1.489 +                                               bool aIsVertical,
   1.490 +                                               bool aIsIndeterminate,
   1.491 +                                               bool aIsClassic)
   1.492 +{
   1.493 +  NS_ASSERTION(aFrame, "bad frame pointer");
   1.494 +  NS_ASSERTION(aWidgetRect, "bad rect pointer");
   1.495 +
   1.496 +  int32_t frameSize = aIsVertical ? aWidgetRect->bottom - aWidgetRect->top
   1.497 +                                  : aWidgetRect->right - aWidgetRect->left;
   1.498 +
   1.499 +  // Recycle a set of progress pulse timers - these timers control the position
   1.500 +  // of all progress overlays and indeterminate chunks that get rendered.
   1.501 +  double span = aIsIndeterminate ? kProgressIndeterminateTimeSpan
   1.502 +                                 : kProgressDeterminateTimeSpan;
   1.503 +  TimeDuration period;
   1.504 +  if (!aIsIndeterminate) {
   1.505 +    if (TimeStamp::Now() > (mProgressDeterminateTimeStamp +
   1.506 +                            TimeDuration::FromSeconds(span))) {
   1.507 +      mProgressDeterminateTimeStamp = TimeStamp::Now();
   1.508 +    }
   1.509 +    period = TimeStamp::Now() - mProgressDeterminateTimeStamp;
   1.510 +  } else {
   1.511 +    if (TimeStamp::Now() > (mProgressIndeterminateTimeStamp +
   1.512 +                            TimeDuration::FromSeconds(span))) {
   1.513 +      mProgressIndeterminateTimeStamp = TimeStamp::Now();
   1.514 +    }
   1.515 +    period = TimeStamp::Now() - mProgressIndeterminateTimeStamp;
   1.516 +  }
   1.517 +
   1.518 +  double percent = period / TimeDuration::FromSeconds(span);
   1.519 +
   1.520 +  if (!aIsVertical && IsFrameRTL(aFrame))
   1.521 +    percent = 1 - percent;
   1.522 +
   1.523 +  RECT overlayRect = *aWidgetRect;
   1.524 +  int32_t overlaySize;
   1.525 +  if (!aIsClassic) {
   1.526 +    overlaySize = GetProgressOverlaySize(aIsVertical, aIsIndeterminate);
   1.527 +  } else {
   1.528 +    overlaySize = kProgressClassicOverlaySize;
   1.529 +  } 
   1.530 +
   1.531 +  // Calculate a bounds that is larger than the meters frame such that the
   1.532 +  // overlay starts and ends completely off the edge of the frame:
   1.533 +  // [overlay][frame][overlay]
   1.534 +  // This also yields a nice delay on rotation. Use overlaySize as the minimum
   1.535 +  // size for [overlay] based on the graphics dims. If [frame] is larger, use
   1.536 +  // the frame size instead.
   1.537 +  int trackWidth = frameSize > overlaySize ? frameSize : overlaySize;
   1.538 +  if (!aIsVertical) {
   1.539 +    int xPos = aWidgetRect->left - trackWidth;
   1.540 +    xPos += (int)ceil(((double)(trackWidth*2) * percent));
   1.541 +    overlayRect.left = xPos;
   1.542 +    overlayRect.right = xPos + overlaySize;
   1.543 +  } else {
   1.544 +    int yPos = aWidgetRect->bottom + trackWidth;
   1.545 +    yPos -= (int)ceil(((double)(trackWidth*2) * percent));
   1.546 +    overlayRect.bottom = yPos;
   1.547 +    overlayRect.top = yPos - overlaySize;
   1.548 +  }
   1.549 +  return overlayRect;
   1.550 +}
   1.551 +
   1.552 +/*
   1.553 + * DrawChunkProgressMeter - renders an xp style chunked progress meter. Called
   1.554 + * by DrawProgressMeter.
   1.555 + *
   1.556 + * @param aTheme       progress theme handle
   1.557 + * @param aHdc         hdc returned by gfxWindowsNativeDrawing
   1.558 + * @param aPart        the PP_X progress part
   1.559 + * @param aState       the theme state
   1.560 + * @param aFrame       the elements frame
   1.561 + * @param aWidgetRect  bounding rect for the widget
   1.562 + * @param aClipRect    dirty rect that needs drawing.
   1.563 + * @param aAppUnits    app units per device pixel
   1.564 + * @param aIsIndeterm  is an indeterminate progress?
   1.565 + * @param aIsVertical  render a vertical progress?
   1.566 + * @param aIsRtl       direction is rtl
   1.567 + */
   1.568 +static void
   1.569 +DrawChunkProgressMeter(HTHEME aTheme, HDC aHdc, int aPart,
   1.570 +                       int aState, nsIFrame* aFrame, RECT* aWidgetRect,
   1.571 +                       RECT* aClipRect, gfxFloat aAppUnits, bool aIsIndeterm,
   1.572 +                       bool aIsVertical, bool aIsRtl)
   1.573 +{
   1.574 +  NS_ASSERTION(aTheme, "Bad theme.");
   1.575 +  NS_ASSERTION(aHdc, "Bad hdc.");
   1.576 +  NS_ASSERTION(aWidgetRect, "Bad rect.");
   1.577 +  NS_ASSERTION(aClipRect, "Bad clip rect.");
   1.578 +  NS_ASSERTION(aFrame, "Bad frame.");
   1.579 +
   1.580 +  // For horizontal meters, the theme lib paints the right graphic but doesn't
   1.581 +  // paint the chunks, so we do that manually. For vertical meters, the theme
   1.582 +  // library draws everything correctly.
   1.583 +  if (aIsVertical) {
   1.584 +    DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
   1.585 +    return;
   1.586 +  }
   1.587 +
   1.588 +  // query for the proper chunk metrics
   1.589 +  int chunkSize, spaceSize;
   1.590 +  if (FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
   1.591 +                            TMT_PROGRESSCHUNKSIZE, &chunkSize)) ||
   1.592 +      FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
   1.593 +                            TMT_PROGRESSSPACESIZE, &spaceSize))) {
   1.594 +    DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
   1.595 +    return;
   1.596 +  }
   1.597 +
   1.598 +  // render chunks
   1.599 +  if (!aIsRtl || aIsIndeterm) {
   1.600 +    for (int chunk = aWidgetRect->left; chunk <= aWidgetRect->right;
   1.601 +         chunk += (chunkSize+spaceSize)) {
   1.602 +      if (!aIsIndeterm && ((chunk + chunkSize) > aWidgetRect->right)) {
   1.603 +        // aWidgetRect->right represents the end of the meter. Partial blocks
   1.604 +        // don't get rendered with one exception, so exit here if we don't have
   1.605 +        // a full chunk to draw.
   1.606 +        // The above is true *except* when the meter is at 100% fill, in which
   1.607 +        // case Windows renders any remaining partial block. Query the parent
   1.608 +        // frame to find out if we're at 100%.
   1.609 +        if (!IsProgressMeterFilled(aFrame)) {
   1.610 +          break;
   1.611 +        }
   1.612 +      }
   1.613 +      RECT bounds =
   1.614 +        { chunk, aWidgetRect->top, chunk + chunkSize, aWidgetRect->bottom };
   1.615 +      DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
   1.616 +    }
   1.617 +  } else {
   1.618 +    // rtl needs to grow in the opposite direction to look right.
   1.619 +    for (int chunk = aWidgetRect->right; chunk >= aWidgetRect->left;
   1.620 +         chunk -= (chunkSize+spaceSize)) {
   1.621 +      if ((chunk - chunkSize) < aWidgetRect->left) {
   1.622 +        if (!IsProgressMeterFilled(aFrame)) {
   1.623 +          break;
   1.624 +        }
   1.625 +      }
   1.626 +      RECT bounds =
   1.627 +        { chunk - chunkSize, aWidgetRect->top, chunk, aWidgetRect->bottom };
   1.628 +      DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
   1.629 +    }
   1.630 +  }
   1.631 +}
   1.632 +
   1.633 +/*
   1.634 + * DrawProgressMeter - render an appropriate progress meter based on progress
   1.635 + * meter style, orientation, and os. Note, this does not render the underlying
   1.636 + * progress track.
   1.637 + *
   1.638 + * @param aFrame       the widget frame
   1.639 + * @param aWidgetType  type of widget
   1.640 + * @param aTheme       progress theme handle
   1.641 + * @param aHdc         hdc returned by gfxWindowsNativeDrawing
   1.642 + * @param aPart        the PP_X progress part
   1.643 + * @param aState       the theme state
   1.644 + * @param aWidgetRect  bounding rect for the widget
   1.645 + * @param aClipRect    dirty rect that needs drawing.
   1.646 + * @param aAppUnits    app units per device pixel
   1.647 + */
   1.648 +void
   1.649 +nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
   1.650 +                                          HANDLE aTheme, HDC aHdc,
   1.651 +                                          int aPart, int aState,
   1.652 +                                          RECT* aWidgetRect, RECT* aClipRect,
   1.653 +                                          gfxFloat aAppUnits)
   1.654 +{
   1.655 +  if (!aFrame || !aTheme || !aHdc)
   1.656 +    return;
   1.657 +
   1.658 +  NS_ASSERTION(aWidgetRect, "bad rect pointer");
   1.659 +  NS_ASSERTION(aClipRect, "bad clip rect pointer");
   1.660 +
   1.661 +  RECT adjWidgetRect, adjClipRect;
   1.662 +  adjWidgetRect = *aWidgetRect;
   1.663 +  adjClipRect = *aClipRect;
   1.664 +  if (!IsVistaOrLater()) {
   1.665 +    // Adjust clipping out by one pixel. XP progress meters are inset,
   1.666 +    // Vista+ are not.
   1.667 +    InflateRect(&adjWidgetRect, 1, 1);
   1.668 +    InflateRect(&adjClipRect, 1, 1);
   1.669 +  }
   1.670 +
   1.671 +  nsIFrame* parentFrame = aFrame->GetParent();
   1.672 +  if (!parentFrame) {
   1.673 +    // We have no parent to work with, just bail.
   1.674 +    NS_WARNING("No parent frame for progress rendering. Can't paint.");
   1.675 +    return;
   1.676 +  }
   1.677 +
   1.678 +  EventStates eventStates = GetContentState(parentFrame, aWidgetType);
   1.679 +  bool vertical = IsVerticalProgress(parentFrame) ||
   1.680 +                  aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL;
   1.681 +  bool indeterminate = IsIndeterminateProgress(parentFrame, eventStates);
   1.682 +  bool animate = indeterminate;
   1.683 +
   1.684 +  if (IsVistaOrLater()) {
   1.685 +    // Vista and up progress meter is fill style, rendered here. We render
   1.686 +    // the pulse overlay in the follow up section below.
   1.687 +    DrawThemeBackground(aTheme, aHdc, aPart, aState,
   1.688 +                        &adjWidgetRect, &adjClipRect);
   1.689 +    if (!IsProgressMeterFilled(aFrame)) {
   1.690 +      animate = true;
   1.691 +    }
   1.692 +  } else if (!indeterminate) {
   1.693 +    // XP progress meters are 'chunk' style.
   1.694 +    DrawChunkProgressMeter(aTheme, aHdc, aPart, aState, aFrame,
   1.695 +                           &adjWidgetRect, &adjClipRect, aAppUnits,
   1.696 +                           indeterminate, vertical, IsFrameRTL(aFrame));
   1.697 +  }    
   1.698 +
   1.699 +  if (animate) {
   1.700 +    // Indeterminate rendering
   1.701 +    int32_t overlayPart = GetProgressOverlayStyle(vertical);
   1.702 +    RECT overlayRect =
   1.703 +      CalculateProgressOverlayRect(aFrame, &adjWidgetRect, vertical,
   1.704 +                                   indeterminate, false);
   1.705 +    if (IsVistaOrLater()) {
   1.706 +      DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect,
   1.707 +                          &adjClipRect);
   1.708 +    } else {
   1.709 +      DrawChunkProgressMeter(aTheme, aHdc, overlayPart, aState, aFrame,
   1.710 +                             &overlayRect, &adjClipRect, aAppUnits,
   1.711 +                             indeterminate, vertical, IsFrameRTL(aFrame));
   1.712 +    }
   1.713 +
   1.714 +    if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) {
   1.715 +      NS_WARNING("unable to animate progress widget!");
   1.716 +    }
   1.717 +  }
   1.718 +}
   1.719 +
   1.720 +HANDLE
   1.721 +nsNativeThemeWin::GetTheme(uint8_t aWidgetType)
   1.722 +{ 
   1.723 +  if (!IsVistaOrLater()) {
   1.724 +    // On XP or earlier, render dropdowns as textfields;
   1.725 +    // doing it the right way works fine with the MS themes,
   1.726 +    // but breaks on a lot of custom themes (presumably because MS
   1.727 +    // apps do the textfield border business as well).
   1.728 +    if (aWidgetType == NS_THEME_DROPDOWN)
   1.729 +      aWidgetType = NS_THEME_TEXTFIELD;
   1.730 +  }
   1.731 +
   1.732 +  switch (aWidgetType) {
   1.733 +    case NS_THEME_BUTTON:
   1.734 +    case NS_THEME_RADIO:
   1.735 +    case NS_THEME_CHECKBOX:
   1.736 +    case NS_THEME_GROUPBOX:
   1.737 +      return nsUXThemeData::GetTheme(eUXButton);
   1.738 +    case NS_THEME_NUMBER_INPUT:
   1.739 +    case NS_THEME_TEXTFIELD:
   1.740 +    case NS_THEME_TEXTFIELD_MULTILINE:
   1.741 +      return nsUXThemeData::GetTheme(eUXEdit);
   1.742 +    case NS_THEME_TOOLTIP:
   1.743 +      // XP/2K3 should force a classic treatment of tooltips
   1.744 +      return !IsVistaOrLater() ?
   1.745 +        nullptr : nsUXThemeData::GetTheme(eUXTooltip);
   1.746 +    case NS_THEME_TOOLBOX:
   1.747 +      return nsUXThemeData::GetTheme(eUXRebar);
   1.748 +    case NS_THEME_WIN_MEDIA_TOOLBOX:
   1.749 +      return nsUXThemeData::GetTheme(eUXMediaRebar);
   1.750 +    case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX:
   1.751 +      return nsUXThemeData::GetTheme(eUXCommunicationsRebar);
   1.752 +    case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX:
   1.753 +      return nsUXThemeData::GetTheme(eUXBrowserTabBarRebar);
   1.754 +    case NS_THEME_TOOLBAR:
   1.755 +    case NS_THEME_TOOLBAR_BUTTON:
   1.756 +    case NS_THEME_TOOLBAR_SEPARATOR:
   1.757 +      return nsUXThemeData::GetTheme(eUXToolbar);
   1.758 +    case NS_THEME_PROGRESSBAR:
   1.759 +    case NS_THEME_PROGRESSBAR_VERTICAL:
   1.760 +    case NS_THEME_PROGRESSBAR_CHUNK:
   1.761 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
   1.762 +      return nsUXThemeData::GetTheme(eUXProgress);
   1.763 +    case NS_THEME_TAB:
   1.764 +    case NS_THEME_TAB_PANEL:
   1.765 +    case NS_THEME_TAB_PANELS:
   1.766 +      return nsUXThemeData::GetTheme(eUXTab);
   1.767 +    case NS_THEME_SCROLLBAR:
   1.768 +    case NS_THEME_SCROLLBAR_SMALL:
   1.769 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
   1.770 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
   1.771 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
   1.772 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
   1.773 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
   1.774 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
   1.775 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
   1.776 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
   1.777 +      return nsUXThemeData::GetTheme(eUXScrollbar);
   1.778 +    case NS_THEME_RANGE:
   1.779 +    case NS_THEME_RANGE_THUMB:
   1.780 +    case NS_THEME_SCALE_HORIZONTAL:
   1.781 +    case NS_THEME_SCALE_VERTICAL:
   1.782 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
   1.783 +    case NS_THEME_SCALE_THUMB_VERTICAL:
   1.784 +      return nsUXThemeData::GetTheme(eUXTrackbar);
   1.785 +    case NS_THEME_SPINNER_UP_BUTTON:
   1.786 +    case NS_THEME_SPINNER_DOWN_BUTTON:
   1.787 +      return nsUXThemeData::GetTheme(eUXSpin);
   1.788 +    case NS_THEME_STATUSBAR:
   1.789 +    case NS_THEME_STATUSBAR_PANEL:
   1.790 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
   1.791 +    case NS_THEME_RESIZER:
   1.792 +      return nsUXThemeData::GetTheme(eUXStatus);
   1.793 +    case NS_THEME_DROPDOWN:
   1.794 +    case NS_THEME_DROPDOWN_BUTTON:
   1.795 +      return nsUXThemeData::GetTheme(eUXCombobox);
   1.796 +    case NS_THEME_TREEVIEW_HEADER_CELL:
   1.797 +    case NS_THEME_TREEVIEW_HEADER_SORTARROW:
   1.798 +      return nsUXThemeData::GetTheme(eUXHeader);
   1.799 +    case NS_THEME_LISTBOX:
   1.800 +    case NS_THEME_LISTBOX_LISTITEM:
   1.801 +    case NS_THEME_TREEVIEW:
   1.802 +    case NS_THEME_TREEVIEW_TWISTY_OPEN:
   1.803 +    case NS_THEME_TREEVIEW_TREEITEM:
   1.804 +      return nsUXThemeData::GetTheme(eUXListview);
   1.805 +    case NS_THEME_MENUBAR:
   1.806 +    case NS_THEME_MENUPOPUP:
   1.807 +    case NS_THEME_MENUITEM:
   1.808 +    case NS_THEME_CHECKMENUITEM:
   1.809 +    case NS_THEME_RADIOMENUITEM:
   1.810 +    case NS_THEME_MENUCHECKBOX:
   1.811 +    case NS_THEME_MENURADIO:
   1.812 +    case NS_THEME_MENUSEPARATOR:
   1.813 +    case NS_THEME_MENUARROW:
   1.814 +    case NS_THEME_MENUIMAGE:
   1.815 +    case NS_THEME_MENUITEMTEXT:
   1.816 +      return nsUXThemeData::GetTheme(eUXMenu);
   1.817 +    case NS_THEME_WINDOW_TITLEBAR:
   1.818 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
   1.819 +    case NS_THEME_WINDOW_FRAME_LEFT:
   1.820 +    case NS_THEME_WINDOW_FRAME_RIGHT:
   1.821 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
   1.822 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
   1.823 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
   1.824 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
   1.825 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
   1.826 +    case NS_THEME_WINDOW_BUTTON_BOX:
   1.827 +    case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
   1.828 +    case NS_THEME_WIN_GLASS:
   1.829 +    case NS_THEME_WIN_BORDERLESS_GLASS:
   1.830 +      return nsUXThemeData::GetTheme(eUXWindowFrame);
   1.831 +  }
   1.832 +  return nullptr;
   1.833 +}
   1.834 +
   1.835 +int32_t
   1.836 +nsNativeThemeWin::StandardGetState(nsIFrame* aFrame, uint8_t aWidgetType,
   1.837 +                                   bool wantFocused)
   1.838 +{
   1.839 +  EventStates eventState = GetContentState(aFrame, aWidgetType);
   1.840 +  if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
   1.841 +    return TS_ACTIVE;
   1.842 +  if (eventState.HasState(NS_EVENT_STATE_HOVER))
   1.843 +    return TS_HOVER;
   1.844 +  if (wantFocused && eventState.HasState(NS_EVENT_STATE_FOCUS))
   1.845 +    return TS_FOCUSED;
   1.846 +
   1.847 +  return TS_NORMAL;
   1.848 +}
   1.849 +
   1.850 +bool
   1.851 +nsNativeThemeWin::IsMenuActive(nsIFrame *aFrame, uint8_t aWidgetType)
   1.852 +{
   1.853 +  nsIContent* content = aFrame->GetContent();
   1.854 +  if (content->IsXUL() &&
   1.855 +      content->NodeInfo()->Equals(nsGkAtoms::richlistitem))
   1.856 +    return CheckBooleanAttr(aFrame, nsGkAtoms::selected);
   1.857 +
   1.858 +  return CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
   1.859 +}
   1.860 +
   1.861 +/**
   1.862 + * aPart is filled in with the UXTheme part code. On return, values > 0
   1.863 + * are the actual UXTheme part code; -1 means the widget will be drawn by
   1.864 + * us; 0 means that we should use part code 0, which isn't a real part code
   1.865 + * but elicits some kind of default behaviour from UXTheme when drawing
   1.866 + * (but isThemeBackgroundPartiallyTransparent may not work).
   1.867 + */
   1.868 +nsresult 
   1.869 +nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType, 
   1.870 +                                       int32_t& aPart, int32_t& aState)
   1.871 +{
   1.872 +  if (!IsVistaOrLater()) {
   1.873 +    // See GetTheme
   1.874 +    if (aWidgetType == NS_THEME_DROPDOWN)
   1.875 +      aWidgetType = NS_THEME_TEXTFIELD;
   1.876 +  }
   1.877 +
   1.878 +  switch (aWidgetType) {
   1.879 +    case NS_THEME_BUTTON: {
   1.880 +      aPart = BP_BUTTON;
   1.881 +      if (!aFrame) {
   1.882 +        aState = TS_NORMAL;
   1.883 +        return NS_OK;
   1.884 +      }
   1.885 +
   1.886 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
   1.887 +      if (IsDisabled(aFrame, eventState)) {
   1.888 +        aState = TS_DISABLED;
   1.889 +        return NS_OK;
   1.890 +      } else if (IsOpenButton(aFrame) ||
   1.891 +                 IsCheckedButton(aFrame)) {
   1.892 +        aState = TS_ACTIVE;
   1.893 +        return NS_OK;
   1.894 +      }
   1.895 +
   1.896 +      aState = StandardGetState(aFrame, aWidgetType, true);
   1.897 +      
   1.898 +      // Check for default dialog buttons.  These buttons should always look
   1.899 +      // focused.
   1.900 +      if (aState == TS_NORMAL && IsDefaultButton(aFrame))
   1.901 +        aState = TS_FOCUSED;
   1.902 +      return NS_OK;
   1.903 +    }
   1.904 +    case NS_THEME_CHECKBOX:
   1.905 +    case NS_THEME_RADIO: {
   1.906 +      bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
   1.907 +      aPart = isCheckbox ? BP_CHECKBOX : BP_RADIO;
   1.908 +
   1.909 +      enum InputState {
   1.910 +        UNCHECKED = 0, CHECKED, INDETERMINATE
   1.911 +      };
   1.912 +      InputState inputState = UNCHECKED;
   1.913 +      bool isXULCheckboxRadio = false;
   1.914 +
   1.915 +      if (!aFrame) {
   1.916 +        aState = TS_NORMAL;
   1.917 +      } else {
   1.918 +        if (GetCheckedOrSelected(aFrame, !isCheckbox)) {
   1.919 +          inputState = CHECKED;
   1.920 +        } if (isCheckbox && GetIndeterminate(aFrame)) {
   1.921 +          inputState = INDETERMINATE;
   1.922 +        }
   1.923 +
   1.924 +        EventStates eventState =
   1.925 +          GetContentState(isXULCheckboxRadio ? aFrame->GetParent() : aFrame,
   1.926 +                          aWidgetType);
   1.927 +        if (IsDisabled(aFrame, eventState)) {
   1.928 +          aState = TS_DISABLED;
   1.929 +        } else {
   1.930 +          aState = StandardGetState(aFrame, aWidgetType, false);
   1.931 +        }
   1.932 +      }
   1.933 +
   1.934 +      // 4 unchecked states, 4 checked states, 4 indeterminate states.
   1.935 +      aState += inputState * 4;
   1.936 +      return NS_OK;
   1.937 +    }
   1.938 +    case NS_THEME_GROUPBOX: {
   1.939 +      aPart = BP_GROUPBOX;
   1.940 +      aState = TS_NORMAL;
   1.941 +      // Since we don't support groupbox disabled and GBS_DISABLED looks the
   1.942 +      // same as GBS_NORMAL don't bother supporting GBS_DISABLED.
   1.943 +      return NS_OK;
   1.944 +    }
   1.945 +    case NS_THEME_NUMBER_INPUT:
   1.946 +    case NS_THEME_TEXTFIELD:
   1.947 +    case NS_THEME_TEXTFIELD_MULTILINE: {
   1.948 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
   1.949 +
   1.950 +      if (IsVistaOrLater()) {
   1.951 +        /* Note: the NOSCROLL type has a rounded corner in each
   1.952 +         * corner.  The more specific HSCROLL, VSCROLL, HVSCROLL types
   1.953 +         * have side and/or top/bottom edges rendered as straight
   1.954 +         * horizontal lines with sharp corners to accommodate a
   1.955 +         * scrollbar.  However, the scrollbar gets rendered on top of
   1.956 +         * this for us, so we don't care, and can just use NOSCROLL
   1.957 +         * here.
   1.958 +         */
   1.959 +        aPart = TFP_EDITBORDER_NOSCROLL;
   1.960 +
   1.961 +        if (!aFrame) {
   1.962 +          aState = TFS_EDITBORDER_NORMAL;
   1.963 +        } else if (IsDisabled(aFrame, eventState)) {
   1.964 +          aState = TFS_EDITBORDER_DISABLED;
   1.965 +        } else if (IsReadOnly(aFrame)) {
   1.966 +          /* no special read-only state */
   1.967 +          aState = TFS_EDITBORDER_NORMAL;
   1.968 +        } else {
   1.969 +          nsIContent* content = aFrame->GetContent();
   1.970 +
   1.971 +          /* XUL textboxes don't get focused themselves, because they have child
   1.972 +           * html:input.. but we can check the XUL focused attributes on them
   1.973 +           */
   1.974 +          if (content && content->IsXUL() && IsFocused(aFrame))
   1.975 +            aState = TFS_EDITBORDER_FOCUSED;
   1.976 +          else if (eventState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS))
   1.977 +            aState = TFS_EDITBORDER_FOCUSED;
   1.978 +          else if (eventState.HasState(NS_EVENT_STATE_HOVER))
   1.979 +            aState = TFS_EDITBORDER_HOVER;
   1.980 +          else
   1.981 +            aState = TFS_EDITBORDER_NORMAL;
   1.982 +        }
   1.983 +      } else {
   1.984 +        aPart = TFP_TEXTFIELD;
   1.985 +        
   1.986 +        if (!aFrame)
   1.987 +          aState = TS_NORMAL;
   1.988 +        else if (IsDisabled(aFrame, eventState))
   1.989 +          aState = TS_DISABLED;
   1.990 +        else if (IsReadOnly(aFrame))
   1.991 +          aState = TFS_READONLY;
   1.992 +        else
   1.993 +          aState = StandardGetState(aFrame, aWidgetType, true);
   1.994 +      }
   1.995 +
   1.996 +      return NS_OK;
   1.997 +    }
   1.998 +    case NS_THEME_TOOLTIP: {
   1.999 +      aPart = TTP_STANDARD;
  1.1000 +      aState = TS_NORMAL;
  1.1001 +      return NS_OK;
  1.1002 +    }
  1.1003 +    case NS_THEME_PROGRESSBAR:
  1.1004 +    case NS_THEME_PROGRESSBAR_VERTICAL: {
  1.1005 +      // Note IsVerticalProgress only tests for orient css attrribute,
  1.1006 +      // NS_THEME_PROGRESSBAR_VERTICAL is dedicated to -moz-appearance:
  1.1007 +      // progressbar-vertical.
  1.1008 +      bool vertical = IsVerticalProgress(aFrame) ||
  1.1009 +                      aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL;
  1.1010 +      aPart = vertical ? PP_BARVERT : PP_BAR;
  1.1011 +      aState = PBBS_NORMAL;
  1.1012 +      return NS_OK;
  1.1013 +    }
  1.1014 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.1015 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: {
  1.1016 +      nsIFrame* parentFrame = aFrame->GetParent();
  1.1017 +      EventStates eventStates = GetContentState(parentFrame, aWidgetType);
  1.1018 +      if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
  1.1019 +          IsVerticalProgress(parentFrame)) {
  1.1020 +        aPart = IsVistaOrLater() ?
  1.1021 +          PP_FILLVERT : PP_CHUNKVERT;
  1.1022 +      } else {
  1.1023 +        aPart = IsVistaOrLater() ?
  1.1024 +          PP_FILL : PP_CHUNK;
  1.1025 +      }
  1.1026 +
  1.1027 +      aState = PBBVS_NORMAL;
  1.1028 +      return NS_OK;
  1.1029 +    }
  1.1030 +    case NS_THEME_TOOLBAR_BUTTON: {
  1.1031 +      aPart = BP_BUTTON;
  1.1032 +      if (!aFrame) {
  1.1033 +        aState = TS_NORMAL;
  1.1034 +        return NS_OK;
  1.1035 +      }
  1.1036 +
  1.1037 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1038 +      if (IsDisabled(aFrame, eventState)) {
  1.1039 +        aState = TS_DISABLED;
  1.1040 +        return NS_OK;
  1.1041 +      }
  1.1042 +      if (IsOpenButton(aFrame)) {
  1.1043 +        aState = TS_ACTIVE;
  1.1044 +        return NS_OK;
  1.1045 +      }
  1.1046 +
  1.1047 +      if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
  1.1048 +        aState = TS_ACTIVE;
  1.1049 +      else if (eventState.HasState(NS_EVENT_STATE_HOVER)) {
  1.1050 +        if (IsCheckedButton(aFrame))
  1.1051 +          aState = TB_HOVER_CHECKED;
  1.1052 +        else
  1.1053 +          aState = TS_HOVER;
  1.1054 +      }
  1.1055 +      else {
  1.1056 +        if (IsCheckedButton(aFrame))
  1.1057 +          aState = TB_CHECKED;
  1.1058 +        else
  1.1059 +          aState = TS_NORMAL;
  1.1060 +      }
  1.1061 +     
  1.1062 +      return NS_OK;
  1.1063 +    }
  1.1064 +    case NS_THEME_TOOLBAR_SEPARATOR: {
  1.1065 +      aPart = TP_SEPARATOR;
  1.1066 +      aState = TS_NORMAL;
  1.1067 +      return NS_OK;
  1.1068 +    }
  1.1069 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.1070 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.1071 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.1072 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
  1.1073 +      aPart = SP_BUTTON;
  1.1074 +      aState = (aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP)*4;
  1.1075 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1076 +      if (!aFrame)
  1.1077 +        aState += TS_NORMAL;
  1.1078 +      else if (IsDisabled(aFrame, eventState))
  1.1079 +        aState += TS_DISABLED;
  1.1080 +      else {
  1.1081 +        nsIFrame *parent = aFrame->GetParent();
  1.1082 +        EventStates parentState =
  1.1083 +          GetContentState(parent, parent->StyleDisplay()->mAppearance);
  1.1084 +        if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
  1.1085 +          aState += TS_ACTIVE;
  1.1086 +        else if (eventState.HasState(NS_EVENT_STATE_HOVER))
  1.1087 +          aState += TS_HOVER;
  1.1088 +        else if (IsVistaOrLater() &&
  1.1089 +                 parentState.HasState(NS_EVENT_STATE_HOVER))
  1.1090 +          aState = (aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP) + SP_BUTTON_IMPLICIT_HOVER_BASE;
  1.1091 +        else
  1.1092 +          aState += TS_NORMAL;
  1.1093 +      }
  1.1094 +      return NS_OK;
  1.1095 +    }
  1.1096 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
  1.1097 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL: {
  1.1098 +      aPart = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL) ?
  1.1099 +              SP_TRACKSTARTHOR : SP_TRACKSTARTVERT;
  1.1100 +      aState = TS_NORMAL;
  1.1101 +      return NS_OK;
  1.1102 +    }
  1.1103 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.1104 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL: {
  1.1105 +      aPart = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) ?
  1.1106 +              SP_THUMBHOR : SP_THUMBVERT;
  1.1107 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1108 +      if (!aFrame)
  1.1109 +        aState = TS_NORMAL;
  1.1110 +      else if (IsDisabled(aFrame, eventState))
  1.1111 +        aState = TS_DISABLED;
  1.1112 +      else {
  1.1113 +        if (eventState.HasState(NS_EVENT_STATE_ACTIVE)) // Hover is not also a requirement for
  1.1114 +                                                        // the thumb, since the drag is not canceled
  1.1115 +                                                        // when you move outside the thumb.
  1.1116 +          aState = TS_ACTIVE;
  1.1117 +        else if (eventState.HasState(NS_EVENT_STATE_HOVER))
  1.1118 +          aState = TS_HOVER;
  1.1119 +        else 
  1.1120 +          aState = TS_NORMAL;
  1.1121 +      }
  1.1122 +      return NS_OK;
  1.1123 +    }
  1.1124 +    case NS_THEME_RANGE:
  1.1125 +    case NS_THEME_SCALE_HORIZONTAL:
  1.1126 +    case NS_THEME_SCALE_VERTICAL: {
  1.1127 +      if (aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
  1.1128 +          (aWidgetType == NS_THEME_RANGE &&
  1.1129 +           IsRangeHorizontal(aFrame))) {
  1.1130 +        aPart = TKP_TRACK;
  1.1131 +        aState = TRS_NORMAL;
  1.1132 +      } else {
  1.1133 +        aPart = TKP_TRACKVERT;
  1.1134 +        aState = TRVS_NORMAL;
  1.1135 +      }
  1.1136 +      return NS_OK;
  1.1137 +    }
  1.1138 +    case NS_THEME_RANGE_THUMB:
  1.1139 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.1140 +    case NS_THEME_SCALE_THUMB_VERTICAL: {
  1.1141 +      if (aWidgetType == NS_THEME_RANGE_THUMB) {
  1.1142 +        if (IsRangeHorizontal(aFrame)) {
  1.1143 +          aPart = TKP_THUMBBOTTOM;
  1.1144 +        } else {
  1.1145 +          aPart = IsFrameRTL(aFrame) ? TKP_THUMBLEFT : TKP_THUMBRIGHT;
  1.1146 +        }
  1.1147 +      } else {
  1.1148 +        aPart = (aWidgetType == NS_THEME_SCALE_THUMB_HORIZONTAL) ?
  1.1149 +                TKP_THUMB : TKP_THUMBVERT;
  1.1150 +      }
  1.1151 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1152 +      if (!aFrame)
  1.1153 +        aState = TS_NORMAL;
  1.1154 +      else if (IsDisabled(aFrame, eventState)) {
  1.1155 +        aState = TKP_DISABLED;
  1.1156 +      }
  1.1157 +      else {
  1.1158 +        if (eventState.HasState(NS_EVENT_STATE_ACTIVE)) // Hover is not also a requirement for
  1.1159 +                                                        // the thumb, since the drag is not canceled
  1.1160 +                                                        // when you move outside the thumb.
  1.1161 +          aState = TS_ACTIVE;
  1.1162 +        else if (eventState.HasState(NS_EVENT_STATE_FOCUS))
  1.1163 +          aState = TKP_FOCUSED;
  1.1164 +        else if (eventState.HasState(NS_EVENT_STATE_HOVER))
  1.1165 +          aState = TS_HOVER;
  1.1166 +        else
  1.1167 +          aState = TS_NORMAL;
  1.1168 +      }
  1.1169 +      return NS_OK;
  1.1170 +    }
  1.1171 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.1172 +    case NS_THEME_SPINNER_DOWN_BUTTON: {
  1.1173 +      aPart = (aWidgetType == NS_THEME_SPINNER_UP_BUTTON) ?
  1.1174 +              SPNP_UP : SPNP_DOWN;
  1.1175 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1176 +      if (!aFrame)
  1.1177 +        aState = TS_NORMAL;
  1.1178 +      else if (IsDisabled(aFrame, eventState))
  1.1179 +        aState = TS_DISABLED;
  1.1180 +      else
  1.1181 +        aState = StandardGetState(aFrame, aWidgetType, false);
  1.1182 +      return NS_OK;    
  1.1183 +    }
  1.1184 +    case NS_THEME_TOOLBOX:
  1.1185 +    case NS_THEME_WIN_MEDIA_TOOLBOX:
  1.1186 +    case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX:
  1.1187 +    case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX:
  1.1188 +    case NS_THEME_STATUSBAR:
  1.1189 +    case NS_THEME_SCROLLBAR:
  1.1190 +    case NS_THEME_SCROLLBAR_SMALL: {
  1.1191 +      aState = 0;
  1.1192 +      if (IsVistaOrLater()) {
  1.1193 +        // On vista, they have a part
  1.1194 +        aPart = RP_BACKGROUND;
  1.1195 +      } else {
  1.1196 +        // Otherwise, they don't.  (But I bet
  1.1197 +        // RP_BACKGROUND would work here, too);
  1.1198 +        aPart = 0;
  1.1199 +      }
  1.1200 +      return NS_OK;
  1.1201 +    }
  1.1202 +    case NS_THEME_TOOLBAR: {
  1.1203 +      // Use -1 to indicate we don't wish to have the theme background drawn
  1.1204 +      // for this item. We will pass any nessessary information via aState,
  1.1205 +      // and will render the item using separate code.
  1.1206 +      aPart = -1;
  1.1207 +      aState = 0;
  1.1208 +      if (aFrame) {
  1.1209 +        nsIContent* content = aFrame->GetContent();
  1.1210 +        nsIContent* parent = content->GetParent();
  1.1211 +        // XXXzeniko hiding the first toolbar will result in an unwanted margin
  1.1212 +        if (parent && parent->GetFirstChild() == content) {
  1.1213 +          aState = 1;
  1.1214 +        }
  1.1215 +      }
  1.1216 +      return NS_OK;
  1.1217 +    }
  1.1218 +    case NS_THEME_STATUSBAR_PANEL:
  1.1219 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
  1.1220 +    case NS_THEME_RESIZER: {
  1.1221 +      aPart = (aWidgetType - NS_THEME_STATUSBAR_PANEL) + 1;
  1.1222 +      aState = TS_NORMAL;
  1.1223 +      return NS_OK;
  1.1224 +    }
  1.1225 +    case NS_THEME_TREEVIEW:
  1.1226 +    case NS_THEME_LISTBOX: {
  1.1227 +      aPart = TREEVIEW_BODY;
  1.1228 +      aState = TS_NORMAL;
  1.1229 +      return NS_OK;
  1.1230 +    }
  1.1231 +    case NS_THEME_TAB_PANELS: {
  1.1232 +      aPart = TABP_PANELS;
  1.1233 +      aState = TS_NORMAL;
  1.1234 +      return NS_OK;
  1.1235 +    }
  1.1236 +    case NS_THEME_TAB_PANEL: {
  1.1237 +      aPart = TABP_PANEL;
  1.1238 +      aState = TS_NORMAL;
  1.1239 +      return NS_OK;
  1.1240 +    }
  1.1241 +    case NS_THEME_TAB: {
  1.1242 +      aPart = TABP_TAB;
  1.1243 +      if (!aFrame) {
  1.1244 +        aState = TS_NORMAL;
  1.1245 +        return NS_OK;
  1.1246 +      }
  1.1247 +
  1.1248 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1249 +      if (IsDisabled(aFrame, eventState)) {
  1.1250 +        aState = TS_DISABLED;
  1.1251 +        return NS_OK;
  1.1252 +      }
  1.1253 +
  1.1254 +      if (IsSelectedTab(aFrame)) {
  1.1255 +        aPart = TABP_TAB_SELECTED;
  1.1256 +        aState = TS_ACTIVE; // The selected tab is always "pressed".
  1.1257 +      }
  1.1258 +      else
  1.1259 +        aState = StandardGetState(aFrame, aWidgetType, true);
  1.1260 +      
  1.1261 +      return NS_OK;
  1.1262 +    }
  1.1263 +    case NS_THEME_TREEVIEW_HEADER_SORTARROW: {
  1.1264 +      // XXX Probably will never work due to a bug in the Luna theme.
  1.1265 +      aPart = 4;
  1.1266 +      aState = 1;
  1.1267 +      return NS_OK;
  1.1268 +    }
  1.1269 +    case NS_THEME_TREEVIEW_HEADER_CELL: {
  1.1270 +      aPart = 1;
  1.1271 +      if (!aFrame) {
  1.1272 +        aState = TS_NORMAL;
  1.1273 +        return NS_OK;
  1.1274 +      }
  1.1275 +      
  1.1276 +      aState = StandardGetState(aFrame, aWidgetType, true);
  1.1277 +      
  1.1278 +      return NS_OK;
  1.1279 +    }
  1.1280 +    case NS_THEME_DROPDOWN: {
  1.1281 +      nsIContent* content = aFrame->GetContent();
  1.1282 +      bool isHTML = content && content->IsHTML();
  1.1283 +      bool useDropBorder = isHTML || IsMenuListEditable(aFrame);
  1.1284 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1285 +
  1.1286 +      /* On Vista/Win7, we use CBP_DROPBORDER instead of DROPFRAME for HTML
  1.1287 +       * content or for editable menulists; this gives us the thin outline,
  1.1288 +       * instead of the gradient-filled background */
  1.1289 +      if (useDropBorder)
  1.1290 +        aPart = CBP_DROPBORDER;
  1.1291 +      else
  1.1292 +        aPart = CBP_DROPFRAME;
  1.1293 +
  1.1294 +      if (IsDisabled(aFrame, eventState)) {
  1.1295 +        aState = TS_DISABLED;
  1.1296 +      } else if (IsReadOnly(aFrame)) {
  1.1297 +        aState = TS_NORMAL;
  1.1298 +      } else if (IsOpenButton(aFrame)) {
  1.1299 +        aState = TS_ACTIVE;
  1.1300 +      } else {
  1.1301 +        if (useDropBorder && (eventState.HasState(NS_EVENT_STATE_FOCUS) || IsFocused(aFrame)))
  1.1302 +          aState = TS_ACTIVE;
  1.1303 +        else if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
  1.1304 +          aState = TS_ACTIVE;
  1.1305 +        else if (eventState.HasState(NS_EVENT_STATE_HOVER))
  1.1306 +          aState = TS_HOVER;
  1.1307 +        else
  1.1308 +          aState = TS_NORMAL;
  1.1309 +      }
  1.1310 +
  1.1311 +      return NS_OK;
  1.1312 +    }
  1.1313 +    case NS_THEME_DROPDOWN_BUTTON: {
  1.1314 +      bool isHTML = IsHTMLContent(aFrame);
  1.1315 +      nsIFrame* parentFrame = aFrame->GetParent();
  1.1316 +      bool isMenulist = !isHTML && parentFrame->GetType() == nsGkAtoms::menuFrame;
  1.1317 +      bool isOpen = false;
  1.1318 +
  1.1319 +      // HTML select and XUL menulist dropdown buttons get state from the parent.
  1.1320 +      if (isHTML || isMenulist)
  1.1321 +        aFrame = parentFrame;
  1.1322 +
  1.1323 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1324 +      aPart = IsVistaOrLater() ?
  1.1325 +        CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
  1.1326 +
  1.1327 +      // For HTML controls with author styling, we should fall
  1.1328 +      // back to the old dropmarker style to avoid clashes with
  1.1329 +      // author-specified backgrounds and borders (bug #441034)
  1.1330 +      if (isHTML && IsWidgetStyled(aFrame->PresContext(), aFrame, NS_THEME_DROPDOWN))
  1.1331 +        aPart = CBP_DROPMARKER;
  1.1332 +
  1.1333 +      if (IsDisabled(aFrame, eventState)) {
  1.1334 +        aState = TS_DISABLED;
  1.1335 +        return NS_OK;
  1.1336 +      }
  1.1337 +
  1.1338 +      if (isHTML) {
  1.1339 +        nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
  1.1340 +        isOpen = (ccf && ccf->IsDroppedDown());
  1.1341 +      }
  1.1342 +      else
  1.1343 +        isOpen = IsOpenButton(aFrame);
  1.1344 +
  1.1345 +      if (IsVistaOrLater()) {
  1.1346 +        if (isHTML || IsMenuListEditable(aFrame)) {
  1.1347 +          if (isOpen) {
  1.1348 +            /* Hover is propagated, but we need to know whether we're
  1.1349 +             * hovering just the combobox frame, not the dropdown frame.
  1.1350 +             * But, we can't get that information, since hover is on the
  1.1351 +             * content node, and they share the same content node.  So,
  1.1352 +             * instead, we cheat -- if the dropdown is open, we always
  1.1353 +             * show the hover state.  This looks fine in practice.
  1.1354 +             */
  1.1355 +            aState = TS_HOVER;
  1.1356 +            return NS_OK;
  1.1357 +          }
  1.1358 +        } else {
  1.1359 +          /* On Vista, the dropdown indicator on a menulist button in  
  1.1360 +           * chrome is not given a hover effect. When the frame isn't
  1.1361 +           * isn't HTML content, we cheat and force the dropdown state
  1.1362 +           * to be normal. (Bug 430434)
  1.1363 +           */
  1.1364 +          aState = TS_NORMAL;
  1.1365 +          return NS_OK;
  1.1366 +        }
  1.1367 +      }
  1.1368 +
  1.1369 +      aState = TS_NORMAL;
  1.1370 +
  1.1371 +      // Dropdown button active state doesn't need :hover.
  1.1372 +      if (eventState.HasState(NS_EVENT_STATE_ACTIVE)) {
  1.1373 +        if (isOpen && (isHTML || isMenulist)) {
  1.1374 +          // XXX Button should look active until the mouse is released, but
  1.1375 +          //     without making it look active when the popup is clicked.
  1.1376 +          return NS_OK;
  1.1377 +        }
  1.1378 +        aState = TS_ACTIVE;
  1.1379 +      }
  1.1380 +      else if (eventState.HasState(NS_EVENT_STATE_HOVER)) {
  1.1381 +        // No hover effect for XUL menulists and autocomplete dropdown buttons
  1.1382 +        // while the dropdown menu is open.
  1.1383 +        if (isOpen) {
  1.1384 +          // XXX HTML select dropdown buttons should have the hover effect when
  1.1385 +          //     hovering the combobox frame, but not the popup frame.
  1.1386 +          return NS_OK;
  1.1387 +        }
  1.1388 +        aState = TS_HOVER;
  1.1389 +      }
  1.1390 +      return NS_OK;
  1.1391 +    }
  1.1392 +    case NS_THEME_MENUPOPUP: {
  1.1393 +      aPart = MENU_POPUPBACKGROUND;
  1.1394 +      aState = MB_ACTIVE;
  1.1395 +      return NS_OK;
  1.1396 +    }
  1.1397 +    case NS_THEME_MENUITEM:
  1.1398 +    case NS_THEME_CHECKMENUITEM: 
  1.1399 +    case NS_THEME_RADIOMENUITEM: {
  1.1400 +      bool isTopLevel = false;
  1.1401 +      bool isOpen = false;
  1.1402 +      bool isHover = false;
  1.1403 +      nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
  1.1404 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1405 +
  1.1406 +      isTopLevel = IsTopLevelMenu(aFrame);
  1.1407 +
  1.1408 +      if (menuFrame)
  1.1409 +        isOpen = menuFrame->IsOpen();
  1.1410 +
  1.1411 +      isHover = IsMenuActive(aFrame, aWidgetType);
  1.1412 +
  1.1413 +      if (isTopLevel) {
  1.1414 +        aPart = MENU_BARITEM;
  1.1415 +
  1.1416 +        if (isOpen)
  1.1417 +          aState = MBI_PUSHED;
  1.1418 +        else if (isHover)
  1.1419 +          aState = MBI_HOT;
  1.1420 +        else
  1.1421 +          aState = MBI_NORMAL;
  1.1422 +
  1.1423 +        // the disabled states are offset by 3
  1.1424 +        if (IsDisabled(aFrame, eventState))
  1.1425 +          aState += 3;
  1.1426 +      } else {
  1.1427 +        aPart = MENU_POPUPITEM;
  1.1428 +
  1.1429 +        if (isHover)
  1.1430 +          aState = MPI_HOT;
  1.1431 +        else
  1.1432 +          aState = MPI_NORMAL;
  1.1433 +
  1.1434 +        // the disabled states are offset by 2
  1.1435 +        if (IsDisabled(aFrame, eventState))
  1.1436 +          aState += 2;
  1.1437 +      }
  1.1438 +
  1.1439 +      return NS_OK;
  1.1440 +    }
  1.1441 +    case NS_THEME_MENUSEPARATOR:
  1.1442 +      aPart = MENU_POPUPSEPARATOR;
  1.1443 +      aState = 0;
  1.1444 +      return NS_OK;
  1.1445 +    case NS_THEME_MENUARROW:
  1.1446 +      {
  1.1447 +        aPart = MENU_POPUPSUBMENU;
  1.1448 +        EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1449 +        aState = IsDisabled(aFrame, eventState) ? MSM_DISABLED : MSM_NORMAL;
  1.1450 +        return NS_OK;
  1.1451 +      }
  1.1452 +    case NS_THEME_MENUCHECKBOX:
  1.1453 +    case NS_THEME_MENURADIO:
  1.1454 +      {
  1.1455 +        bool isChecked;
  1.1456 +        EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1457 +
  1.1458 +        // NOTE: we can probably use NS_EVENT_STATE_CHECKED
  1.1459 +        isChecked = CheckBooleanAttr(aFrame, nsGkAtoms::checked);
  1.1460 +
  1.1461 +        aPart = MENU_POPUPCHECK;
  1.1462 +        aState = MC_CHECKMARKNORMAL;
  1.1463 +
  1.1464 +        // Radio states are offset by 2
  1.1465 +        if (aWidgetType == NS_THEME_MENURADIO)
  1.1466 +          aState += 2;
  1.1467 +
  1.1468 +        // the disabled states are offset by 1
  1.1469 +        if (IsDisabled(aFrame, eventState))
  1.1470 +          aState += 1;
  1.1471 +
  1.1472 +        return NS_OK;
  1.1473 +      }
  1.1474 +    case NS_THEME_MENUITEMTEXT:
  1.1475 +    case NS_THEME_MENUIMAGE:
  1.1476 +      aPart = -1;
  1.1477 +      aState = 0;
  1.1478 +      return NS_OK;
  1.1479 +
  1.1480 +    case NS_THEME_WINDOW_TITLEBAR:
  1.1481 +      aPart = mozilla::widget::themeconst::WP_CAPTION;
  1.1482 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.1483 +      return NS_OK;
  1.1484 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.1485 +      aPart = mozilla::widget::themeconst::WP_MAXCAPTION;
  1.1486 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.1487 +      return NS_OK;
  1.1488 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.1489 +      aPart = mozilla::widget::themeconst::WP_FRAMELEFT;
  1.1490 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.1491 +      return NS_OK;
  1.1492 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.1493 +      aPart = mozilla::widget::themeconst::WP_FRAMERIGHT;
  1.1494 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.1495 +      return NS_OK;
  1.1496 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.1497 +      aPart = mozilla::widget::themeconst::WP_FRAMEBOTTOM;
  1.1498 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.1499 +      return NS_OK;
  1.1500 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.1501 +      aPart = mozilla::widget::themeconst::WP_CLOSEBUTTON;
  1.1502 +      aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
  1.1503 +      return NS_OK;
  1.1504 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.1505 +      aPart = mozilla::widget::themeconst::WP_MINBUTTON;
  1.1506 +      aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
  1.1507 +      return NS_OK;
  1.1508 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.1509 +      aPart = mozilla::widget::themeconst::WP_MAXBUTTON;
  1.1510 +      aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
  1.1511 +      return NS_OK;
  1.1512 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.1513 +      aPart = mozilla::widget::themeconst::WP_RESTOREBUTTON;
  1.1514 +      aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
  1.1515 +      return NS_OK;
  1.1516 +    case NS_THEME_WINDOW_BUTTON_BOX:
  1.1517 +    case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
  1.1518 +    case NS_THEME_WIN_GLASS:
  1.1519 +    case NS_THEME_WIN_BORDERLESS_GLASS:
  1.1520 +      aPart = -1;
  1.1521 +      aState = 0;
  1.1522 +      return NS_OK;
  1.1523 +  }
  1.1524 +
  1.1525 +  aPart = 0;
  1.1526 +  aState = 0;
  1.1527 +  return NS_ERROR_FAILURE;
  1.1528 +}
  1.1529 +
  1.1530 +static bool
  1.1531 +AssumeThemePartAndStateAreTransparent(int32_t aPart, int32_t aState)
  1.1532 +{
  1.1533 +  if (aPart == MENU_POPUPITEM && aState == MBI_NORMAL) {
  1.1534 +    return true;
  1.1535 +  }
  1.1536 +  return false;
  1.1537 +}
  1.1538 +
  1.1539 +NS_IMETHODIMP
  1.1540 +nsNativeThemeWin::DrawWidgetBackground(nsRenderingContext* aContext,
  1.1541 +                                       nsIFrame* aFrame,
  1.1542 +                                       uint8_t aWidgetType,
  1.1543 +                                       const nsRect& aRect,
  1.1544 +                                       const nsRect& aDirtyRect)
  1.1545 +{
  1.1546 +  HANDLE theme = GetTheme(aWidgetType);
  1.1547 +  if (!theme)
  1.1548 +    return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
  1.1549 +
  1.1550 +  // ^^ without the right sdk, assume xp theming and fall through.
  1.1551 +  if (nsUXThemeData::CheckForCompositor()) {
  1.1552 +    switch (aWidgetType) {
  1.1553 +      case NS_THEME_WINDOW_TITLEBAR:
  1.1554 +      case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.1555 +      case NS_THEME_WINDOW_FRAME_LEFT:
  1.1556 +      case NS_THEME_WINDOW_FRAME_RIGHT:
  1.1557 +      case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.1558 +        // Nothing to draw, these areas are glass. Minimum dimensions
  1.1559 +        // should be set, so xul content should be layed out correctly.
  1.1560 +        return NS_OK;
  1.1561 +      break;
  1.1562 +      case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.1563 +      case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.1564 +      case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.1565 +      case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.1566 +        // Not conventional bitmaps, can't be retrieved. If we fall
  1.1567 +        // through here and call the theme library we'll get aero
  1.1568 +        // basic bitmaps. 
  1.1569 +        return NS_OK;
  1.1570 +      break;
  1.1571 +      case NS_THEME_WIN_GLASS:
  1.1572 +      case NS_THEME_WIN_BORDERLESS_GLASS:
  1.1573 +        // Nothing to draw, this is the glass background.
  1.1574 +        return NS_OK;
  1.1575 +      case NS_THEME_WINDOW_BUTTON_BOX:
  1.1576 +      case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
  1.1577 +        // We handle these through nsIWidget::UpdateThemeGeometries
  1.1578 +        return NS_OK;
  1.1579 +      break;
  1.1580 +    }
  1.1581 +  }
  1.1582 +
  1.1583 +  int32_t part, state;
  1.1584 +  nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
  1.1585 +  if (NS_FAILED(rv))
  1.1586 +    return rv;
  1.1587 +
  1.1588 +  if (AssumeThemePartAndStateAreTransparent(part, state)) {
  1.1589 +    return NS_OK;
  1.1590 +  }
  1.1591 +
  1.1592 +  gfxFloat p2a = gfxFloat(aContext->AppUnitsPerDevPixel());
  1.1593 +  RECT widgetRect;
  1.1594 +  RECT clipRect;
  1.1595 +  gfxRect tr(aRect.x, aRect.y, aRect.width, aRect.height),
  1.1596 +          dr(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
  1.1597 +
  1.1598 +  tr.ScaleInverse(p2a);
  1.1599 +  dr.ScaleInverse(p2a);
  1.1600 +
  1.1601 +  nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
  1.1602 +
  1.1603 +  gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
  1.1604 +
  1.1605 +RENDER_AGAIN:
  1.1606 +
  1.1607 +  HDC hdc = nativeDrawing.BeginNativeDrawing();
  1.1608 +  if (!hdc)
  1.1609 +    return NS_ERROR_FAILURE;
  1.1610 +
  1.1611 +  nativeDrawing.TransformToNativeRect(tr, widgetRect);
  1.1612 +  nativeDrawing.TransformToNativeRect(dr, clipRect);
  1.1613 +
  1.1614 +#if 0
  1.1615 +  {
  1.1616 +    PR_LOG(gWindowsLog, PR_LOG_ERROR,
  1.1617 +           (stderr, "xform: %f %f %f %f [%f %f]\n", m.xx, m.yx, m.xy, m.yy, 
  1.1618 +            m.x0, m.y0));
  1.1619 +    PR_LOG(gWindowsLog, PR_LOG_ERROR,
  1.1620 +           (stderr, "tr: [%d %d %d %d]\ndr: [%d %d %d %d]\noff: [%f %f]\n",
  1.1621 +            tr.x, tr.y, tr.width, tr.height, dr.x, dr.y, dr.width, dr.height,
  1.1622 +            offset.x, offset.y));
  1.1623 +  }
  1.1624 +#endif
  1.1625 +
  1.1626 +  if (aWidgetType == NS_THEME_WINDOW_TITLEBAR) {
  1.1627 +    // Clip out the left and right corners of the frame, all we want in
  1.1628 +    // is the middle section.
  1.1629 +    widgetRect.left -= GetSystemMetrics(SM_CXFRAME);
  1.1630 +    widgetRect.right += GetSystemMetrics(SM_CXFRAME);
  1.1631 +  } else if (aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED) {
  1.1632 +    // The origin of the window is off screen when maximized and windows
  1.1633 +    // doesn't compensate for this in rendering the background. Push the
  1.1634 +    // top of the bitmap down by SM_CYFRAME so we get the full graphic.
  1.1635 +    widgetRect.top += GetSystemMetrics(SM_CYFRAME);
  1.1636 +  } else if (aWidgetType == NS_THEME_TAB) {
  1.1637 +    // For left edge and right edge tabs, we need to adjust the widget
  1.1638 +    // rects and clip rects so that the edges don't get drawn.
  1.1639 +    bool isLeft = IsLeftToSelectedTab(aFrame);
  1.1640 +    bool isRight = !isLeft && IsRightToSelectedTab(aFrame);
  1.1641 +
  1.1642 +    if (isLeft || isRight) {
  1.1643 +      // HACK ALERT: There appears to be no way to really obtain this value, so we're forced
  1.1644 +      // to just use the default value for Luna (which also happens to be correct for
  1.1645 +      // all the other skins I've tried).
  1.1646 +      int32_t edgeSize = 2;
  1.1647 +    
  1.1648 +      // Armed with the size of the edge, we now need to either shift to the left or to the
  1.1649 +      // right.  The clip rect won't include this extra area, so we know that we're
  1.1650 +      // effectively shifting the edge out of view (such that it won't be painted).
  1.1651 +      if (isLeft)
  1.1652 +        // The right edge should not be drawn.  Extend our rect by the edge size.
  1.1653 +        widgetRect.right += edgeSize;
  1.1654 +      else
  1.1655 +        // The left edge should not be drawn.  Move the widget rect's left coord back.
  1.1656 +        widgetRect.left -= edgeSize;
  1.1657 +    }
  1.1658 +  }
  1.1659 +  else if (aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE) {
  1.1660 +    OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_MINIMIZE);
  1.1661 +  }
  1.1662 +  else if (aWidgetType == NS_THEME_WINDOW_BUTTON_MAXIMIZE ||
  1.1663 +           aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
  1.1664 +    OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_RESTORE);
  1.1665 +  }
  1.1666 +  else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) {
  1.1667 +    OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_CLOSE);
  1.1668 +  }
  1.1669 +
  1.1670 +  // widgetRect is the bounding box for a widget, yet the scale track is only
  1.1671 +  // a small portion of this size, so the edges of the scale need to be
  1.1672 +  // adjusted to the real size of the track.
  1.1673 +  if (aWidgetType == NS_THEME_RANGE ||
  1.1674 +      aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
  1.1675 +      aWidgetType == NS_THEME_SCALE_VERTICAL) {
  1.1676 +    RECT contentRect;
  1.1677 +    GetThemeBackgroundContentRect(theme, hdc, part, state, &widgetRect, &contentRect);
  1.1678 +
  1.1679 +    SIZE siz;
  1.1680 +    GetThemePartSize(theme, hdc, part, state, &widgetRect, TS_TRUE, &siz);
  1.1681 +
  1.1682 +    // When rounding is necessary, we round the position of the track
  1.1683 +    // away from the chevron of the thumb to make it look better.
  1.1684 +    if (aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
  1.1685 +        (aWidgetType == NS_THEME_RANGE && IsRangeHorizontal(aFrame))) {
  1.1686 +      contentRect.top += (contentRect.bottom - contentRect.top - siz.cy) / 2;
  1.1687 +      contentRect.bottom = contentRect.top + siz.cy;
  1.1688 +    }
  1.1689 +    else {
  1.1690 +      if (!IsFrameRTL(aFrame)) {
  1.1691 +        contentRect.left += (contentRect.right - contentRect.left - siz.cx) / 2;
  1.1692 +        contentRect.right = contentRect.left + siz.cx;
  1.1693 +      } else {
  1.1694 +        contentRect.right -= (contentRect.right - contentRect.left - siz.cx) / 2;
  1.1695 +        contentRect.left = contentRect.right - siz.cx;
  1.1696 +      }
  1.1697 +    }
  1.1698 +
  1.1699 +    DrawThemeBackground(theme, hdc, part, state, &contentRect, &clipRect);
  1.1700 +  }
  1.1701 +  else if (aWidgetType == NS_THEME_MENUCHECKBOX || aWidgetType == NS_THEME_MENURADIO)
  1.1702 +  {
  1.1703 +      bool isChecked = false;
  1.1704 +      isChecked = CheckBooleanAttr(aFrame, nsGkAtoms::checked);
  1.1705 +
  1.1706 +      if (isChecked)
  1.1707 +      {
  1.1708 +        int bgState = MCB_NORMAL;
  1.1709 +        EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.1710 +
  1.1711 +        // the disabled states are offset by 1
  1.1712 +        if (IsDisabled(aFrame, eventState))
  1.1713 +          bgState += 1;
  1.1714 +
  1.1715 +        SIZE checkboxBGSize(GetCheckboxBGSize(theme, hdc));
  1.1716 +
  1.1717 +        RECT checkBGRect = widgetRect;
  1.1718 +        if (IsFrameRTL(aFrame)) {
  1.1719 +          checkBGRect.left = checkBGRect.right-checkboxBGSize.cx;
  1.1720 +        } else {
  1.1721 +          checkBGRect.right = checkBGRect.left+checkboxBGSize.cx;
  1.1722 +        }
  1.1723 +
  1.1724 +        // Center the checkbox background vertically in the menuitem
  1.1725 +        checkBGRect.top += (checkBGRect.bottom - checkBGRect.top)/2 - checkboxBGSize.cy/2;
  1.1726 +        checkBGRect.bottom = checkBGRect.top + checkboxBGSize.cy;
  1.1727 +
  1.1728 +        DrawThemeBackground(theme, hdc, MENU_POPUPCHECKBACKGROUND, bgState, &checkBGRect, &clipRect);
  1.1729 +
  1.1730 +        MARGINS checkMargins = GetCheckboxMargins(theme, hdc);
  1.1731 +        RECT checkRect = checkBGRect;
  1.1732 +        checkRect.left += checkMargins.cxLeftWidth;
  1.1733 +        checkRect.right -= checkMargins.cxRightWidth;
  1.1734 +        checkRect.top += checkMargins.cyTopHeight;
  1.1735 +        checkRect.bottom -= checkMargins.cyBottomHeight;
  1.1736 +        DrawThemeBackground(theme, hdc, MENU_POPUPCHECK, state, &checkRect, &clipRect);
  1.1737 +      }
  1.1738 +  }
  1.1739 +  else if (aWidgetType == NS_THEME_MENUPOPUP)
  1.1740 +  {
  1.1741 +    DrawThemeBackground(theme, hdc, MENU_POPUPBORDERS, /* state */ 0, &widgetRect, &clipRect);
  1.1742 +    SIZE borderSize;
  1.1743 +    GetThemePartSize(theme, hdc, MENU_POPUPBORDERS, 0, nullptr, TS_TRUE, &borderSize);
  1.1744 +
  1.1745 +    RECT bgRect = widgetRect;
  1.1746 +    bgRect.top += borderSize.cy;
  1.1747 +    bgRect.bottom -= borderSize.cy;
  1.1748 +    bgRect.left += borderSize.cx;
  1.1749 +    bgRect.right -= borderSize.cx;
  1.1750 +
  1.1751 +    DrawThemeBackground(theme, hdc, MENU_POPUPBACKGROUND, /* state */ 0, &bgRect, &clipRect);
  1.1752 +
  1.1753 +    SIZE gutterSize(GetGutterSize(theme, hdc));
  1.1754 +
  1.1755 +    RECT gutterRect;
  1.1756 +    gutterRect.top = bgRect.top;
  1.1757 +    gutterRect.bottom = bgRect.bottom;
  1.1758 +    if (IsFrameRTL(aFrame)) {
  1.1759 +      gutterRect.right = bgRect.right;
  1.1760 +      gutterRect.left = gutterRect.right-gutterSize.cx;
  1.1761 +    } else {
  1.1762 +      gutterRect.left = bgRect.left;
  1.1763 +      gutterRect.right = gutterRect.left+gutterSize.cx;
  1.1764 +    }
  1.1765 +
  1.1766 +    DrawThemeBGRTLAware(theme, hdc, MENU_POPUPGUTTER, /* state */ 0,
  1.1767 +                        &gutterRect, &clipRect, IsFrameRTL(aFrame));
  1.1768 +  }
  1.1769 +  else if (aWidgetType == NS_THEME_MENUSEPARATOR)
  1.1770 +  {
  1.1771 +    SIZE gutterSize(GetGutterSize(theme,hdc));
  1.1772 +
  1.1773 +    RECT sepRect = widgetRect;
  1.1774 +    if (IsFrameRTL(aFrame))
  1.1775 +      sepRect.right -= gutterSize.cx;
  1.1776 +    else
  1.1777 +      sepRect.left += gutterSize.cx;
  1.1778 +
  1.1779 +    DrawThemeBackground(theme, hdc, MENU_POPUPSEPARATOR, /* state */ 0, &sepRect, &clipRect);
  1.1780 +  }
  1.1781 +  else if (aWidgetType == NS_THEME_MENUARROW)
  1.1782 +  {
  1.1783 +    // We're dpi aware and as such on systems that have dpi > 96 set, the
  1.1784 +    // theme library expects us to do proper positioning and scaling of glyphs.
  1.1785 +    // For NS_THEME_MENUARROW, layout may hand us a widget rect larger than the
  1.1786 +    // glyph rect we request in GetMinimumWidgetSize. To prevent distortion we
  1.1787 +    // have to position and scale what we draw.
  1.1788 +
  1.1789 +    SIZE glyphSize;
  1.1790 +    GetThemePartSize(theme, hdc, part, state, nullptr, TS_TRUE, &glyphSize);
  1.1791 +
  1.1792 +    int32_t widgetHeight = widgetRect.bottom - widgetRect.top;
  1.1793 +
  1.1794 +    RECT renderRect = widgetRect;
  1.1795 +
  1.1796 +    // We request (glyph width * 2, glyph height) in GetMinimumWidgetSize. In
  1.1797 +    // Firefox some menu items provide the full height of the item to us, in
  1.1798 +    // others our widget rect is the exact dims of our arrow glyph. Adjust the
  1.1799 +    // vertical position by the added space, if any exists.
  1.1800 +    renderRect.top += ((widgetHeight - glyphSize.cy) / 2);
  1.1801 +    renderRect.bottom = renderRect.top + glyphSize.cy;
  1.1802 +    // I'm using the width of the arrow glyph for the arrow-side padding.
  1.1803 +    // AFAICT there doesn't appear to be a theme constant we can query
  1.1804 +    // for this value. Generally this looks correct, and has the added
  1.1805 +    // benefit of being a dpi adjusted value.
  1.1806 +    if (!IsFrameRTL(aFrame)) {
  1.1807 +      renderRect.right = widgetRect.right - glyphSize.cx;
  1.1808 +      renderRect.left = renderRect.right - glyphSize.cx;
  1.1809 +    } else {
  1.1810 +      renderRect.left = glyphSize.cx;
  1.1811 +      renderRect.right = renderRect.left + glyphSize.cx;
  1.1812 +    }
  1.1813 +    DrawThemeBGRTLAware(theme, hdc, part, state, &renderRect, &clipRect,
  1.1814 +                        IsFrameRTL(aFrame));
  1.1815 +  }
  1.1816 +  // The following widgets need to be RTL-aware
  1.1817 +  else if (aWidgetType == NS_THEME_RESIZER ||
  1.1818 +           aWidgetType == NS_THEME_DROPDOWN_BUTTON)
  1.1819 +  {
  1.1820 +    DrawThemeBGRTLAware(theme, hdc, part, state,
  1.1821 +                        &widgetRect, &clipRect, IsFrameRTL(aFrame));
  1.1822 +  }
  1.1823 +  else if (aWidgetType == NS_THEME_PROGRESSBAR ||
  1.1824 +           aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL) {
  1.1825 +    // DrawThemeBackground renders each corner with a solid white pixel.
  1.1826 +    // Restore these pixels to the underlying color. Tracks are rendered
  1.1827 +    // using alpha recovery, so this makes the corners transparent.
  1.1828 +    COLORREF color;
  1.1829 +    color = GetPixel(hdc, widgetRect.left, widgetRect.top);
  1.1830 +    DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
  1.1831 +    SetPixel(hdc, widgetRect.left, widgetRect.top, color);
  1.1832 +    SetPixel(hdc, widgetRect.right-1, widgetRect.top, color);
  1.1833 +    SetPixel(hdc, widgetRect.right-1, widgetRect.bottom-1, color);
  1.1834 +    SetPixel(hdc, widgetRect.left, widgetRect.bottom-1, color);
  1.1835 +  }
  1.1836 +  else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
  1.1837 +           aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL) {
  1.1838 +    DrawThemedProgressMeter(aFrame, aWidgetType, theme, hdc, part, state,
  1.1839 +                            &widgetRect, &clipRect, p2a);
  1.1840 +  }
  1.1841 +  // If part is negative, the element wishes us to not render a themed
  1.1842 +  // background, instead opting to be drawn specially below.
  1.1843 +  else if (part >= 0) {
  1.1844 +    DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
  1.1845 +  }
  1.1846 +
  1.1847 +  // Draw focus rectangles for XP HTML checkboxes and radio buttons
  1.1848 +  // XXX it'd be nice to draw these outside of the frame
  1.1849 +  if (((aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO) &&
  1.1850 +        aFrame->GetContent()->IsHTML()) ||
  1.1851 +      aWidgetType == NS_THEME_RANGE ||
  1.1852 +      aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
  1.1853 +      aWidgetType == NS_THEME_SCALE_VERTICAL) {
  1.1854 +      EventStates contentState = GetContentState(aFrame, aWidgetType);
  1.1855 +
  1.1856 +      if (contentState.HasState(NS_EVENT_STATE_FOCUS)) {
  1.1857 +        POINT vpOrg;
  1.1858 +        HPEN hPen = nullptr;
  1.1859 +
  1.1860 +        uint8_t id = SaveDC(hdc);
  1.1861 +
  1.1862 +        ::SelectClipRgn(hdc, nullptr);
  1.1863 +        ::GetViewportOrgEx(hdc, &vpOrg);
  1.1864 +        ::SetBrushOrgEx(hdc, vpOrg.x + widgetRect.left, vpOrg.y + widgetRect.top, nullptr);
  1.1865 +
  1.1866 +        // On vista, choose our own colors and draw an XP style half focus rect
  1.1867 +        // for focused checkboxes and a full rect when active.
  1.1868 +        if (IsVistaOrLater() &&
  1.1869 +            aWidgetType == NS_THEME_CHECKBOX) {
  1.1870 +          LOGBRUSH lb;
  1.1871 +          lb.lbStyle = BS_SOLID;
  1.1872 +          lb.lbColor = RGB(255,255,255);
  1.1873 +          lb.lbHatch = 0;
  1.1874 +
  1.1875 +          hPen = ::ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, nullptr);
  1.1876 +          ::SelectObject(hdc, hPen);
  1.1877 +
  1.1878 +          // If pressed, draw the upper left corner of the dotted rect.
  1.1879 +          if (contentState.HasState(NS_EVENT_STATE_ACTIVE)) {
  1.1880 +            ::MoveToEx(hdc, widgetRect.left, widgetRect.bottom-1, nullptr);
  1.1881 +            ::LineTo(hdc, widgetRect.left, widgetRect.top);
  1.1882 +            ::LineTo(hdc, widgetRect.right-1, widgetRect.top);
  1.1883 +          }
  1.1884 +
  1.1885 +          // Draw the lower right corner of the dotted rect.
  1.1886 +          ::MoveToEx(hdc, widgetRect.right-1, widgetRect.top, nullptr);
  1.1887 +          ::LineTo(hdc, widgetRect.right-1, widgetRect.bottom-1);
  1.1888 +          ::LineTo(hdc, widgetRect.left, widgetRect.bottom-1);
  1.1889 +        } else {
  1.1890 +          ::SetTextColor(hdc, 0);
  1.1891 +          ::DrawFocusRect(hdc, &widgetRect);
  1.1892 +        }
  1.1893 +        ::RestoreDC(hdc, id);
  1.1894 +        if (hPen) {
  1.1895 +          ::DeleteObject(hPen);
  1.1896 +        }
  1.1897 +      }
  1.1898 +  }
  1.1899 +  else if (aWidgetType == NS_THEME_TOOLBAR && state == 0) {
  1.1900 +    // Draw toolbar separator lines above all toolbars except the first one.
  1.1901 +    // The lines are part of the Rebar theme, which is loaded for NS_THEME_TOOLBOX.
  1.1902 +    theme = GetTheme(NS_THEME_TOOLBOX);
  1.1903 +    if (!theme)
  1.1904 +      return NS_ERROR_FAILURE;
  1.1905 +
  1.1906 +    widgetRect.bottom = widgetRect.top + TB_SEPARATOR_HEIGHT;
  1.1907 +    DrawThemeEdge(theme, hdc, RP_BAND, 0, &widgetRect, EDGE_ETCHED, BF_TOP, nullptr);
  1.1908 +  }
  1.1909 +  else if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL ||
  1.1910 +           aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL)
  1.1911 +  {
  1.1912 +    // Draw the decorative gripper for the scrollbar thumb button, if it fits
  1.1913 +
  1.1914 +    SIZE gripSize;
  1.1915 +    MARGINS thumbMgns;
  1.1916 +    int gripPart = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) ?
  1.1917 +                   SP_GRIPPERHOR : SP_GRIPPERVERT;
  1.1918 +
  1.1919 +    if (GetThemePartSize(theme, hdc, gripPart, state, nullptr, TS_TRUE, &gripSize) == S_OK &&
  1.1920 +        GetThemeMargins(theme, hdc, part, state, TMT_CONTENTMARGINS, nullptr, &thumbMgns) == S_OK &&
  1.1921 +        gripSize.cx + thumbMgns.cxLeftWidth + thumbMgns.cxRightWidth <= widgetRect.right - widgetRect.left &&
  1.1922 +        gripSize.cy + thumbMgns.cyTopHeight + thumbMgns.cyBottomHeight <= widgetRect.bottom - widgetRect.top)
  1.1923 +    {
  1.1924 +      DrawThemeBackground(theme, hdc, gripPart, state, &widgetRect, &clipRect);
  1.1925 +    }
  1.1926 +  }
  1.1927 +
  1.1928 +  nativeDrawing.EndNativeDrawing();
  1.1929 +
  1.1930 +  if (nativeDrawing.ShouldRenderAgain())
  1.1931 +    goto RENDER_AGAIN;
  1.1932 +
  1.1933 +  nativeDrawing.PaintToContext();
  1.1934 +
  1.1935 +  return NS_OK;
  1.1936 +}
  1.1937 +
  1.1938 +NS_IMETHODIMP
  1.1939 +nsNativeThemeWin::GetWidgetBorder(nsDeviceContext* aContext, 
  1.1940 +                                  nsIFrame* aFrame,
  1.1941 +                                  uint8_t aWidgetType,
  1.1942 +                                  nsIntMargin* aResult)
  1.1943 +{
  1.1944 +  HANDLE theme = GetTheme(aWidgetType);
  1.1945 +  if (!theme)
  1.1946 +    return ClassicGetWidgetBorder(aContext, aFrame, aWidgetType, aResult); 
  1.1947 +
  1.1948 +  (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
  1.1949 +
  1.1950 +  if (!WidgetIsContainer(aWidgetType) ||
  1.1951 +      aWidgetType == NS_THEME_TOOLBOX || 
  1.1952 +      aWidgetType == NS_THEME_WIN_MEDIA_TOOLBOX ||
  1.1953 +      aWidgetType == NS_THEME_WIN_COMMUNICATIONS_TOOLBOX ||
  1.1954 +      aWidgetType == NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX ||
  1.1955 +      aWidgetType == NS_THEME_STATUSBAR || 
  1.1956 +      aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL ||
  1.1957 +      aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL ||
  1.1958 +      aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL ||
  1.1959 +      aWidgetType == NS_THEME_MENUITEM || aWidgetType == NS_THEME_CHECKMENUITEM ||
  1.1960 +      aWidgetType == NS_THEME_RADIOMENUITEM || aWidgetType == NS_THEME_MENUPOPUP ||
  1.1961 +      aWidgetType == NS_THEME_MENUIMAGE || aWidgetType == NS_THEME_MENUITEMTEXT ||
  1.1962 +      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR ||
  1.1963 +      aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
  1.1964 +      aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED ||
  1.1965 +      aWidgetType == NS_THEME_WIN_GLASS || aWidgetType == NS_THEME_WIN_BORDERLESS_GLASS)
  1.1966 +    return NS_OK; // Don't worry about it.
  1.1967 +
  1.1968 +  int32_t part, state;
  1.1969 +  nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
  1.1970 +  if (NS_FAILED(rv))
  1.1971 +    return rv;
  1.1972 +
  1.1973 +  if (aWidgetType == NS_THEME_TOOLBAR) {
  1.1974 +    // make space for the separator line above all toolbars but the first
  1.1975 +    if (state == 0)
  1.1976 +      aResult->top = TB_SEPARATOR_HEIGHT;
  1.1977 +    return NS_OK;
  1.1978 +  }
  1.1979 +
  1.1980 +  // Get our info.
  1.1981 +  RECT outerRect; // Create a fake outer rect.
  1.1982 +  outerRect.top = outerRect.left = 100;
  1.1983 +  outerRect.right = outerRect.bottom = 200;
  1.1984 +  RECT contentRect(outerRect);
  1.1985 +  HRESULT res = GetThemeBackgroundContentRect(theme, nullptr, part, state, &outerRect, &contentRect);
  1.1986 +  
  1.1987 +  if (FAILED(res))
  1.1988 +    return NS_ERROR_FAILURE;
  1.1989 +
  1.1990 +  // Now compute the delta in each direction and place it in our
  1.1991 +  // nsIntMargin struct.
  1.1992 +  aResult->top = contentRect.top - outerRect.top;
  1.1993 +  aResult->bottom = outerRect.bottom - contentRect.bottom;
  1.1994 +  aResult->left = contentRect.left - outerRect.left;
  1.1995 +  aResult->right = outerRect.right - contentRect.right;
  1.1996 +
  1.1997 +  // Remove the edges for tabs that are before or after the selected tab,
  1.1998 +  if (aWidgetType == NS_THEME_TAB) {
  1.1999 +    if (IsLeftToSelectedTab(aFrame))
  1.2000 +      // Remove the right edge, since we won't be drawing it.
  1.2001 +      aResult->right = 0;
  1.2002 +    else if (IsRightToSelectedTab(aFrame))
  1.2003 +      // Remove the left edge, since we won't be drawing it.
  1.2004 +      aResult->left = 0;
  1.2005 +  }
  1.2006 +
  1.2007 +  if (aFrame && (aWidgetType == NS_THEME_NUMBER_INPUT ||
  1.2008 +                 aWidgetType == NS_THEME_TEXTFIELD ||
  1.2009 +                 aWidgetType == NS_THEME_TEXTFIELD_MULTILINE)) {
  1.2010 +    nsIContent* content = aFrame->GetContent();
  1.2011 +    if (content && content->IsHTML()) {
  1.2012 +      // We need to pad textfields by 1 pixel, since the caret will draw
  1.2013 +      // flush against the edge by default if we don't.
  1.2014 +      aResult->top++;
  1.2015 +      aResult->left++;
  1.2016 +      aResult->bottom++;
  1.2017 +      aResult->right++;
  1.2018 +    }
  1.2019 +  }
  1.2020 +
  1.2021 +  return NS_OK;
  1.2022 +}
  1.2023 +
  1.2024 +bool
  1.2025 +nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext, 
  1.2026 +                                   nsIFrame* aFrame,
  1.2027 +                                   uint8_t aWidgetType,
  1.2028 +                                   nsIntMargin* aResult)
  1.2029 +{
  1.2030 +  switch (aWidgetType) {
  1.2031 +    // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
  1.2032 +    // and have a meaningful baseline, so they can't have
  1.2033 +    // author-specified padding.
  1.2034 +    case NS_THEME_CHECKBOX:
  1.2035 +    case NS_THEME_RADIO:
  1.2036 +      aResult->SizeTo(0, 0, 0, 0);
  1.2037 +      return true;
  1.2038 +  }
  1.2039 +
  1.2040 +  HANDLE theme = GetTheme(aWidgetType);
  1.2041 +
  1.2042 +  if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX ||
  1.2043 +      aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) {
  1.2044 +    aResult->SizeTo(0, 0, 0, 0);
  1.2045 +
  1.2046 +    // aero glass doesn't display custom buttons
  1.2047 +    if (nsUXThemeData::CheckForCompositor())
  1.2048 +      return true;
  1.2049 +
  1.2050 +    // button padding for standard windows
  1.2051 +    if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX) {
  1.2052 +      aResult->top = GetSystemMetrics(SM_CXFRAME);
  1.2053 +    }
  1.2054 +    return true;
  1.2055 +  }
  1.2056 +
  1.2057 +  // Content padding
  1.2058 +  if (aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
  1.2059 +      aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED) {
  1.2060 +    aResult->SizeTo(0, 0, 0, 0);
  1.2061 +    // XXX Maximized windows have an offscreen offset equal to
  1.2062 +    // the border padding. This should be addressed in nsWindow,
  1.2063 +    // but currently can't be, see UpdateNonClientMargins.
  1.2064 +    if (aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED)
  1.2065 +      aResult->top = GetSystemMetrics(SM_CXFRAME)
  1.2066 +                   + GetSystemMetrics(SM_CXPADDEDBORDER);
  1.2067 +    return true;
  1.2068 +  }
  1.2069 +
  1.2070 +  if (!theme)
  1.2071 +    return ClassicGetWidgetPadding(aContext, aFrame, aWidgetType, aResult);
  1.2072 +
  1.2073 +  if (aWidgetType == NS_THEME_MENUPOPUP)
  1.2074 +  {
  1.2075 +    SIZE popupSize;
  1.2076 +    GetThemePartSize(theme, nullptr, MENU_POPUPBORDERS, /* state */ 0, nullptr, TS_TRUE, &popupSize);
  1.2077 +    aResult->top = aResult->bottom = popupSize.cy;
  1.2078 +    aResult->left = aResult->right = popupSize.cx;
  1.2079 +    return true;
  1.2080 +  }
  1.2081 +
  1.2082 +  if (IsVistaOrLater()) {
  1.2083 +    if (aWidgetType == NS_THEME_NUMBER_INPUT ||
  1.2084 +        aWidgetType == NS_THEME_TEXTFIELD ||
  1.2085 +        aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
  1.2086 +        aWidgetType == NS_THEME_DROPDOWN)
  1.2087 +    {
  1.2088 +      /* If we have author-specified padding for these elements, don't do the fixups below */
  1.2089 +      if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
  1.2090 +        return false;
  1.2091 +    }
  1.2092 +
  1.2093 +    /* textfields need extra pixels on all sides, otherwise they
  1.2094 +     * wrap their content too tightly.  The actual border is drawn 1px
  1.2095 +     * inside the specified rectangle, so Gecko will end up making the
  1.2096 +     * contents look too small.  Instead, we add 2px padding for the
  1.2097 +     * contents and fix this. (Used to be 1px added, see bug 430212)
  1.2098 +     */
  1.2099 +    if (aWidgetType == NS_THEME_NUMBER_INPUT ||
  1.2100 +        aWidgetType == NS_THEME_TEXTFIELD ||
  1.2101 +        aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
  1.2102 +      aResult->top = aResult->bottom = 2;
  1.2103 +      aResult->left = aResult->right = 2;
  1.2104 +      return true;
  1.2105 +    } else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_DROPDOWN) {
  1.2106 +      /* For content menulist controls, we need an extra pixel so
  1.2107 +       * that we have room to draw our focus rectangle stuff.
  1.2108 +       * Otherwise, the focus rect might overlap the control's
  1.2109 +       * border.
  1.2110 +       */
  1.2111 +      aResult->top = aResult->bottom = 1;
  1.2112 +      aResult->left = aResult->right = 1;
  1.2113 +      return true;
  1.2114 +    }
  1.2115 +  }
  1.2116 +
  1.2117 +  int32_t right, left, top, bottom;
  1.2118 +  right = left = top = bottom = 0;
  1.2119 +  switch (aWidgetType)
  1.2120 +  {
  1.2121 +    case NS_THEME_MENUIMAGE:
  1.2122 +        right = 8;
  1.2123 +        left = 3;
  1.2124 +        break;
  1.2125 +    case NS_THEME_MENUCHECKBOX:
  1.2126 +    case NS_THEME_MENURADIO:
  1.2127 +        right = 8;
  1.2128 +        left = 0;
  1.2129 +        break;
  1.2130 +    case NS_THEME_MENUITEMTEXT:
  1.2131 +        // There seem to be exactly 4 pixels from the edge
  1.2132 +        // of the gutter to the text: 2px margin (CSS) + 2px padding (here)
  1.2133 +        {
  1.2134 +          SIZE size(GetGutterSize(theme, nullptr));
  1.2135 +          left = size.cx + 2;
  1.2136 +        }
  1.2137 +        break;
  1.2138 +    case NS_THEME_MENUSEPARATOR:
  1.2139 +        {
  1.2140 +          SIZE size(GetGutterSize(theme, nullptr));
  1.2141 +          left = size.cx + 5;
  1.2142 +          top = 10;
  1.2143 +          bottom = 7;
  1.2144 +        }
  1.2145 +        break;
  1.2146 +    default:
  1.2147 +        return false;
  1.2148 +  }
  1.2149 +
  1.2150 +  if (IsFrameRTL(aFrame))
  1.2151 +  {
  1.2152 +    aResult->right = left;
  1.2153 +    aResult->left = right;
  1.2154 +  }
  1.2155 +  else
  1.2156 +  {
  1.2157 +    aResult->right = right;
  1.2158 +    aResult->left = left;
  1.2159 +  }
  1.2160 +  
  1.2161 +  return true;
  1.2162 +}
  1.2163 +
  1.2164 +bool
  1.2165 +nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext, 
  1.2166 +                                    nsIFrame* aFrame,
  1.2167 +                                    uint8_t aOverflowRect,
  1.2168 +                                    nsRect* aResult)
  1.2169 +{
  1.2170 +  /* This is disabled for now, because it causes invalidation problems --
  1.2171 +   * see bug 420381.  The effect of not updating the overflow area is that
  1.2172 +   * for dropdown buttons in content areas, there is a 1px border on 3 sides
  1.2173 +   * where, if invalidated, the dropdown control probably won't be repainted.
  1.2174 +   * This is fairly minor, as by default there is nothing in that area, and
  1.2175 +   * a border only shows up if the widget is being hovered.
  1.2176 +   */
  1.2177 +#if 0
  1.2178 +  if (IsVistaOrLater()) {
  1.2179 +    /* We explicitly draw dropdown buttons in HTML content 1px bigger
  1.2180 +     * up, right, and bottom so that they overlap the dropdown's border
  1.2181 +     * like they're supposed to.
  1.2182 +     */
  1.2183 +    if (aWidgetType == NS_THEME_DROPDOWN_BUTTON &&
  1.2184 +        IsHTMLContent(aFrame) &&
  1.2185 +        !IsWidgetStyled(aFrame->GetParent()->PresContext(),
  1.2186 +                        aFrame->GetParent(),
  1.2187 +                        NS_THEME_DROPDOWN))
  1.2188 +    {
  1.2189 +      int32_t p2a = aContext->AppUnitsPerDevPixel();
  1.2190 +      /* Note: no overflow on the left */
  1.2191 +      nsMargin m(p2a, p2a, p2a, 0);
  1.2192 +      aOverflowRect->Inflate (m);
  1.2193 +      return true;
  1.2194 +    }
  1.2195 +  }
  1.2196 +#endif
  1.2197 +
  1.2198 +  return false;
  1.2199 +}
  1.2200 +
  1.2201 +NS_IMETHODIMP
  1.2202 +nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* aFrame,
  1.2203 +                                       uint8_t aWidgetType,
  1.2204 +                                       nsIntSize* aResult, bool* aIsOverridable)
  1.2205 +{
  1.2206 +  (*aResult).width = (*aResult).height = 0;
  1.2207 +  *aIsOverridable = true;
  1.2208 +
  1.2209 +  HANDLE theme = GetTheme(aWidgetType);
  1.2210 +  if (!theme)
  1.2211 +    return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
  1.2212 +
  1.2213 +  switch (aWidgetType) {
  1.2214 +    case NS_THEME_GROUPBOX:
  1.2215 +    case NS_THEME_NUMBER_INPUT:
  1.2216 +    case NS_THEME_TEXTFIELD:
  1.2217 +    case NS_THEME_TOOLBOX:
  1.2218 +    case NS_THEME_WIN_MEDIA_TOOLBOX:
  1.2219 +    case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX:
  1.2220 +    case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX:
  1.2221 +    case NS_THEME_TOOLBAR:
  1.2222 +    case NS_THEME_STATUSBAR:
  1.2223 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.2224 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.2225 +    case NS_THEME_TAB_PANELS:
  1.2226 +    case NS_THEME_TAB_PANEL:
  1.2227 +    case NS_THEME_LISTBOX:
  1.2228 +    case NS_THEME_TREEVIEW:
  1.2229 +    case NS_THEME_MENUITEMTEXT:
  1.2230 +    case NS_THEME_WIN_GLASS:
  1.2231 +    case NS_THEME_WIN_BORDERLESS_GLASS:
  1.2232 +      return NS_OK; // Don't worry about it.
  1.2233 +  }
  1.2234 +
  1.2235 +  if (aWidgetType == NS_THEME_MENUITEM && IsTopLevelMenu(aFrame))
  1.2236 +      return NS_OK; // Don't worry about it for top level menus
  1.2237 +
  1.2238 +  // Call GetSystemMetrics to determine size for WinXP scrollbars
  1.2239 +  // (GetThemeSysSize API returns the optimal size for the theme, but 
  1.2240 +  //  Windows appears to always use metrics when drawing standard scrollbars)
  1.2241 +  THEMESIZE sizeReq = TS_TRUE; // Best-fit size
  1.2242 +  switch (aWidgetType) {
  1.2243 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.2244 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.2245 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.2246 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.2247 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.2248 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.2249 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
  1.2250 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.2251 +    case NS_THEME_DROPDOWN_BUTTON:
  1.2252 +      return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
  1.2253 +
  1.2254 +    case NS_THEME_MENUITEM:
  1.2255 +    case NS_THEME_CHECKMENUITEM:
  1.2256 +    case NS_THEME_RADIOMENUITEM:
  1.2257 +      if(!IsTopLevelMenu(aFrame))
  1.2258 +      {
  1.2259 +        SIZE gutterSize(GetGutterSize(theme, nullptr));
  1.2260 +        aResult->width = gutterSize.cx;
  1.2261 +        aResult->height = gutterSize.cy;
  1.2262 +        return NS_OK;
  1.2263 +      }
  1.2264 +      break;
  1.2265 +
  1.2266 +    case NS_THEME_MENUIMAGE:
  1.2267 +    case NS_THEME_MENUCHECKBOX:
  1.2268 +    case NS_THEME_MENURADIO:
  1.2269 +      {
  1.2270 +        SIZE boxSize(GetGutterSize(theme, nullptr));
  1.2271 +        aResult->width = boxSize.cx+2;
  1.2272 +        aResult->height = boxSize.cy;
  1.2273 +        *aIsOverridable = false;
  1.2274 +      }
  1.2275 +
  1.2276 +    case NS_THEME_MENUITEMTEXT:
  1.2277 +      return NS_OK;
  1.2278 +
  1.2279 +    case NS_THEME_PROGRESSBAR:
  1.2280 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2281 +      // Best-fit size for progress meters is too large for most 
  1.2282 +      // themes. We want these widgets to be able to really shrink
  1.2283 +      // down, so use the min-size request value (of 0).
  1.2284 +      sizeReq = TS_MIN; 
  1.2285 +      break;
  1.2286 +
  1.2287 +    case NS_THEME_RESIZER:
  1.2288 +      *aIsOverridable = false;
  1.2289 +      break;
  1.2290 +
  1.2291 +    case NS_THEME_RANGE_THUMB:
  1.2292 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.2293 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.2294 +    {
  1.2295 +      *aIsOverridable = false;
  1.2296 +      // on Vista, GetThemePartAndState returns odd values for
  1.2297 +      // scale thumbs, so use a hardcoded size instead.
  1.2298 +      if (IsVistaOrLater()) {
  1.2299 +        if (aWidgetType == NS_THEME_SCALE_THUMB_HORIZONTAL ||
  1.2300 +            (aWidgetType == NS_THEME_RANGE_THUMB && IsRangeHorizontal(aFrame))) {
  1.2301 +          aResult->width = 12;
  1.2302 +          aResult->height = 20;
  1.2303 +        }
  1.2304 +        else {
  1.2305 +          aResult->width = 20;
  1.2306 +          aResult->height = 12;
  1.2307 +        }
  1.2308 +        return NS_OK;
  1.2309 +      }
  1.2310 +      break;
  1.2311 +    }
  1.2312 +
  1.2313 +    case NS_THEME_SCROLLBAR:
  1.2314 +    {
  1.2315 +      if (nsLookAndFeel::GetInt(
  1.2316 +            nsLookAndFeel::eIntID_UseOverlayScrollbars) != 0) {
  1.2317 +        aResult->SizeTo(::GetSystemMetrics(SM_CXHSCROLL),
  1.2318 +                        ::GetSystemMetrics(SM_CYVSCROLL));
  1.2319 +        return NS_OK;
  1.2320 +      }
  1.2321 +      break;
  1.2322 +    }
  1.2323 +
  1.2324 +    case NS_THEME_TOOLBAR_SEPARATOR:
  1.2325 +      // that's 2px left margin, 2px right margin and 2px separator
  1.2326 +      // (the margin is drawn as part of the separator, though)
  1.2327 +      aResult->width = 6;
  1.2328 +      return NS_OK;
  1.2329 +
  1.2330 +    case NS_THEME_BUTTON:
  1.2331 +      // We should let HTML buttons shrink to their min size.
  1.2332 +      // FIXME bug 403934: We should probably really separate
  1.2333 +      // GetPreferredWidgetSize from GetMinimumWidgetSize, so callers can
  1.2334 +      // use the one they want.
  1.2335 +      if (aFrame->GetContent()->IsHTML()) {
  1.2336 +        sizeReq = TS_MIN;
  1.2337 +      }
  1.2338 +      break;
  1.2339 +
  1.2340 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.2341 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.2342 +      // The only way to get accurate titlebar button info is to query a
  1.2343 +      // window w/buttons when it's visible. nsWindow takes care of this and
  1.2344 +      // stores that info in nsUXThemeData.
  1.2345 +      aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx;
  1.2346 +      aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy;
  1.2347 +      // For XP, subtract 4 from system metrics dimensions.
  1.2348 +      if (!IsVistaOrLater()) {
  1.2349 +        aResult->width -= 4;
  1.2350 +        aResult->height -= 4;
  1.2351 +      }
  1.2352 +      AddPaddingRect(aResult, CAPTIONBUTTON_RESTORE);
  1.2353 +      *aIsOverridable = false;
  1.2354 +      return NS_OK;
  1.2355 +
  1.2356 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.2357 +      aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx;
  1.2358 +      aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy;
  1.2359 +      if (!IsVistaOrLater()) {
  1.2360 +        aResult->width -= 4;
  1.2361 +        aResult->height -= 4;
  1.2362 +      }
  1.2363 +      AddPaddingRect(aResult, CAPTIONBUTTON_MINIMIZE);
  1.2364 +      *aIsOverridable = false;
  1.2365 +      return NS_OK;
  1.2366 +
  1.2367 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.2368 +      aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx;
  1.2369 +      aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy;
  1.2370 +      if (!IsVistaOrLater()) {
  1.2371 +        aResult->width -= 4;
  1.2372 +        aResult->height -= 4;
  1.2373 +      }
  1.2374 +      AddPaddingRect(aResult, CAPTIONBUTTON_CLOSE);
  1.2375 +      *aIsOverridable = false;
  1.2376 +      return NS_OK;
  1.2377 +
  1.2378 +    case NS_THEME_WINDOW_TITLEBAR:
  1.2379 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.2380 +      aResult->height = GetSystemMetrics(SM_CYCAPTION);
  1.2381 +      aResult->height += GetSystemMetrics(SM_CYFRAME);
  1.2382 +      aResult->height += GetSystemMetrics(SM_CXPADDEDBORDER);
  1.2383 +      *aIsOverridable = false;
  1.2384 +      return NS_OK;
  1.2385 +
  1.2386 +    case NS_THEME_WINDOW_BUTTON_BOX:
  1.2387 +    case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
  1.2388 +      if (nsUXThemeData::CheckForCompositor()) {
  1.2389 +        aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cx;
  1.2390 +        aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cy
  1.2391 +                          - GetSystemMetrics(SM_CYFRAME)
  1.2392 +                          - GetSystemMetrics(SM_CXPADDEDBORDER);
  1.2393 +        if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) {
  1.2394 +          aResult->width += 1;
  1.2395 +          aResult->height -= 2;
  1.2396 +        }
  1.2397 +        *aIsOverridable = false;
  1.2398 +        return NS_OK;
  1.2399 +      }
  1.2400 +      break;
  1.2401 +
  1.2402 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.2403 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.2404 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.2405 +      aResult->width = GetSystemMetrics(SM_CXFRAME);
  1.2406 +      aResult->height = GetSystemMetrics(SM_CYFRAME);
  1.2407 +      *aIsOverridable = false;
  1.2408 +      return NS_OK;
  1.2409 +  }
  1.2410 +
  1.2411 +  int32_t part, state;
  1.2412 +  nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
  1.2413 +  if (NS_FAILED(rv))
  1.2414 +    return rv;
  1.2415 +
  1.2416 +  HDC hdc = ::GetDC(nullptr);
  1.2417 +  if (!hdc)
  1.2418 +    return NS_ERROR_FAILURE;
  1.2419 +
  1.2420 +  SIZE sz;
  1.2421 +  GetThemePartSize(theme, hdc, part, state, nullptr, sizeReq, &sz);
  1.2422 +  aResult->width = sz.cx;
  1.2423 +  aResult->height = sz.cy;
  1.2424 +
  1.2425 +  switch(aWidgetType) {
  1.2426 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.2427 +    case NS_THEME_SPINNER_DOWN_BUTTON:
  1.2428 +      aResult->width++;
  1.2429 +      aResult->height = aResult->height / 2 + 1;
  1.2430 +      break;
  1.2431 +
  1.2432 +    case NS_THEME_MENUSEPARATOR:
  1.2433 +    {
  1.2434 +      SIZE gutterSize(GetGutterSize(theme, hdc));
  1.2435 +      aResult->width += gutterSize.cx;
  1.2436 +      break;
  1.2437 +    }
  1.2438 +
  1.2439 +    case NS_THEME_MENUARROW:
  1.2440 +    {
  1.2441 +      // Use the width of the arrow glyph as padding. See the drawing
  1.2442 +      // code for details.
  1.2443 +      aResult->width *= 2;
  1.2444 +      break;
  1.2445 +    }
  1.2446 +  }
  1.2447 +
  1.2448 +  ::ReleaseDC(nullptr, hdc);
  1.2449 +  return NS_OK;
  1.2450 +}
  1.2451 +
  1.2452 +NS_IMETHODIMP
  1.2453 +nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, 
  1.2454 +                                     nsIAtom* aAttribute, bool* aShouldRepaint)
  1.2455 +{
  1.2456 +  // Some widget types just never change state.
  1.2457 +  if (aWidgetType == NS_THEME_TOOLBOX ||
  1.2458 +      aWidgetType == NS_THEME_WIN_MEDIA_TOOLBOX ||
  1.2459 +      aWidgetType == NS_THEME_WIN_COMMUNICATIONS_TOOLBOX ||
  1.2460 +      aWidgetType == NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX ||
  1.2461 +      aWidgetType == NS_THEME_TOOLBAR ||
  1.2462 +      aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_STATUSBAR_PANEL ||
  1.2463 +      aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
  1.2464 +      aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
  1.2465 +      aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
  1.2466 +      aWidgetType == NS_THEME_PROGRESSBAR ||
  1.2467 +      aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
  1.2468 +      aWidgetType == NS_THEME_TOOLTIP ||
  1.2469 +      aWidgetType == NS_THEME_TAB_PANELS ||
  1.2470 +      aWidgetType == NS_THEME_TAB_PANEL ||
  1.2471 +      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR ||
  1.2472 +      aWidgetType == NS_THEME_WIN_GLASS ||
  1.2473 +      aWidgetType == NS_THEME_WIN_BORDERLESS_GLASS) {
  1.2474 +    *aShouldRepaint = false;
  1.2475 +    return NS_OK;
  1.2476 +  }
  1.2477 +
  1.2478 +  if (aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
  1.2479 +      aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED ||
  1.2480 +      aWidgetType == NS_THEME_WINDOW_FRAME_LEFT ||
  1.2481 +      aWidgetType == NS_THEME_WINDOW_FRAME_RIGHT ||
  1.2482 +      aWidgetType == NS_THEME_WINDOW_FRAME_BOTTOM ||
  1.2483 +      aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE ||
  1.2484 +      aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
  1.2485 +      aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
  1.2486 +      aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
  1.2487 +    *aShouldRepaint = true;
  1.2488 +    return NS_OK;
  1.2489 +  }
  1.2490 +
  1.2491 +  // On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
  1.2492 +  if (!IsVistaOrLater() &&
  1.2493 +      (aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL || 
  1.2494 +      aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL)) {
  1.2495 +    *aShouldRepaint = false;
  1.2496 +    return NS_OK;
  1.2497 +  }
  1.2498 +
  1.2499 +  // We need to repaint the dropdown arrow in vista HTML combobox controls when
  1.2500 +  // the control is closed to get rid of the hover effect.
  1.2501 +  if (IsVistaOrLater() &&
  1.2502 +      (aWidgetType == NS_THEME_DROPDOWN || aWidgetType == NS_THEME_DROPDOWN_BUTTON) &&
  1.2503 +      IsHTMLContent(aFrame))
  1.2504 +  {
  1.2505 +    *aShouldRepaint = true;
  1.2506 +    return NS_OK;
  1.2507 +  }
  1.2508 +
  1.2509 +  // XXXdwh Not sure what can really be done here.  Can at least guess for
  1.2510 +  // specific widgets that they're highly unlikely to have certain states.
  1.2511 +  // For example, a toolbar doesn't care about any states.
  1.2512 +  if (!aAttribute) {
  1.2513 +    // Hover/focus/active changed.  Always repaint.
  1.2514 +    *aShouldRepaint = true;
  1.2515 +  }
  1.2516 +  else {
  1.2517 +    // Check the attribute to see if it's relevant.  
  1.2518 +    // disabled, checked, dlgtype, default, etc.
  1.2519 +    *aShouldRepaint = false;
  1.2520 +    if (aAttribute == nsGkAtoms::disabled ||
  1.2521 +        aAttribute == nsGkAtoms::checked ||
  1.2522 +        aAttribute == nsGkAtoms::selected ||
  1.2523 +        aAttribute == nsGkAtoms::readonly ||
  1.2524 +        aAttribute == nsGkAtoms::open ||
  1.2525 +        aAttribute == nsGkAtoms::menuactive ||
  1.2526 +        aAttribute == nsGkAtoms::focused)
  1.2527 +      *aShouldRepaint = true;
  1.2528 +  }
  1.2529 +
  1.2530 +  return NS_OK;
  1.2531 +}
  1.2532 +
  1.2533 +NS_IMETHODIMP
  1.2534 +nsNativeThemeWin::ThemeChanged()
  1.2535 +{
  1.2536 +  nsUXThemeData::Invalidate();
  1.2537 +  return NS_OK;
  1.2538 +}
  1.2539 +
  1.2540 +bool 
  1.2541 +nsNativeThemeWin::ThemeSupportsWidget(nsPresContext* aPresContext,
  1.2542 +                                      nsIFrame* aFrame,
  1.2543 +                                      uint8_t aWidgetType)
  1.2544 +{
  1.2545 +  // XXXdwh We can go even further and call the API to ask if support exists for
  1.2546 +  // specific widgets.
  1.2547 +
  1.2548 +  if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
  1.2549 +    return false;
  1.2550 +
  1.2551 +  HANDLE theme = nullptr;
  1.2552 +  if (aWidgetType == NS_THEME_CHECKBOX_CONTAINER)
  1.2553 +    theme = GetTheme(NS_THEME_CHECKBOX);
  1.2554 +  else if (aWidgetType == NS_THEME_RADIO_CONTAINER)
  1.2555 +    theme = GetTheme(NS_THEME_RADIO);
  1.2556 +  else
  1.2557 +    theme = GetTheme(aWidgetType);
  1.2558 +
  1.2559 +  if ((theme) || (!theme && ClassicThemeSupportsWidget(aPresContext, aFrame, aWidgetType)))
  1.2560 +    // turn off theming for some HTML widgets styled by the page
  1.2561 +    return (!IsWidgetStyled(aPresContext, aFrame, aWidgetType));
  1.2562 +  
  1.2563 +  return false;
  1.2564 +}
  1.2565 +
  1.2566 +bool 
  1.2567 +nsNativeThemeWin::WidgetIsContainer(uint8_t aWidgetType)
  1.2568 +{
  1.2569 +  // XXXdwh At some point flesh all of this out.
  1.2570 +  if (aWidgetType == NS_THEME_DROPDOWN_BUTTON || 
  1.2571 +      aWidgetType == NS_THEME_RADIO ||
  1.2572 +      aWidgetType == NS_THEME_CHECKBOX)
  1.2573 +    return false;
  1.2574 +  return true;
  1.2575 +}
  1.2576 +
  1.2577 +bool
  1.2578 +nsNativeThemeWin::ThemeDrawsFocusForWidget(uint8_t aWidgetType)
  1.2579 +{
  1.2580 +  return false;
  1.2581 +}
  1.2582 +
  1.2583 +bool
  1.2584 +nsNativeThemeWin::ThemeNeedsComboboxDropmarker()
  1.2585 +{
  1.2586 +  return true;
  1.2587 +}
  1.2588 +
  1.2589 +bool
  1.2590 +nsNativeThemeWin::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType)
  1.2591 +{
  1.2592 +  switch (aWidgetType) {
  1.2593 +    case NS_THEME_WINDOW_TITLEBAR:
  1.2594 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.2595 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.2596 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.2597 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.2598 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.2599 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.2600 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.2601 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.2602 +      return true;
  1.2603 +    default:
  1.2604 +      return false;
  1.2605 +  }
  1.2606 +}
  1.2607 +
  1.2608 +bool
  1.2609 +nsNativeThemeWin::ShouldHideScrollbars()
  1.2610 +{
  1.2611 +  return WinUtils::ShouldHideScrollbars();
  1.2612 +}
  1.2613 +
  1.2614 +nsITheme::Transparency
  1.2615 +nsNativeThemeWin::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType)
  1.2616 +{
  1.2617 +  switch (aWidgetType) {
  1.2618 +  case NS_THEME_SCROLLBAR_SMALL:
  1.2619 +  case NS_THEME_SCROLLBAR:
  1.2620 +  case NS_THEME_STATUSBAR:
  1.2621 +    // Knowing that scrollbars and statusbars are opaque improves
  1.2622 +    // performance, because we create layers for them. This better be
  1.2623 +    // true across all Windows themes! If it's not true, we should
  1.2624 +    // paint an opaque background for them to make it true!
  1.2625 +    return eOpaque;
  1.2626 +  case NS_THEME_WIN_GLASS:
  1.2627 +  case NS_THEME_WIN_BORDERLESS_GLASS:
  1.2628 +  case NS_THEME_SCALE_HORIZONTAL:
  1.2629 +  case NS_THEME_SCALE_VERTICAL:
  1.2630 +  case NS_THEME_PROGRESSBAR:
  1.2631 +  case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2632 +  case NS_THEME_PROGRESSBAR_CHUNK:
  1.2633 +  case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.2634 +  case NS_THEME_RANGE:
  1.2635 +    return eTransparent;
  1.2636 +  }
  1.2637 +
  1.2638 +  HANDLE theme = GetTheme(aWidgetType);
  1.2639 +  // For the classic theme we don't really have a way of knowing
  1.2640 +  if (!theme) {
  1.2641 +    // menu backgrounds and tooltips which can't be themed are opaque
  1.2642 +    if (aWidgetType == NS_THEME_MENUPOPUP || aWidgetType == NS_THEME_TOOLTIP) {
  1.2643 +      return eOpaque;
  1.2644 +    }
  1.2645 +    return eUnknownTransparency;
  1.2646 +  }
  1.2647 +
  1.2648 +  int32_t part, state;
  1.2649 +  nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
  1.2650 +  // Fail conservatively
  1.2651 +  NS_ENSURE_SUCCESS(rv, eUnknownTransparency);
  1.2652 +
  1.2653 +  if (part <= 0) {
  1.2654 +    // Not a real part code, so IsThemeBackgroundPartiallyTransparent may
  1.2655 +    // not work, so don't call it.
  1.2656 +    return eUnknownTransparency;
  1.2657 +  }
  1.2658 +
  1.2659 +  if (IsThemeBackgroundPartiallyTransparent(theme, part, state))
  1.2660 +    return eTransparent;
  1.2661 +  return eOpaque;
  1.2662 +}
  1.2663 +
  1.2664 +/* Windows 9x/NT/2000/Classic XP Theme Support */
  1.2665 +
  1.2666 +bool 
  1.2667 +nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext,
  1.2668 +                                      nsIFrame* aFrame,
  1.2669 +                                      uint8_t aWidgetType)
  1.2670 +{
  1.2671 +  switch (aWidgetType) {
  1.2672 +    case NS_THEME_RESIZER:
  1.2673 +    {
  1.2674 +      // The classic native resizer has an opaque grey background which doesn't
  1.2675 +      // match the usually white background of the scrollable container, so
  1.2676 +      // only support the native resizer if not in a scrollframe.
  1.2677 +      nsIFrame* parentFrame = aFrame->GetParent();
  1.2678 +      return (!parentFrame || parentFrame->GetType() != nsGkAtoms::scrollFrame);
  1.2679 +    }
  1.2680 +    case NS_THEME_MENUBAR:
  1.2681 +    case NS_THEME_MENUPOPUP:
  1.2682 +      // Classic non-flat menus are handled almost entirely through CSS.
  1.2683 +      if (!nsUXThemeData::sFlatMenus)
  1.2684 +        return false;
  1.2685 +    case NS_THEME_BUTTON:
  1.2686 +    case NS_THEME_NUMBER_INPUT:
  1.2687 +    case NS_THEME_TEXTFIELD:
  1.2688 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.2689 +    case NS_THEME_CHECKBOX:
  1.2690 +    case NS_THEME_RADIO:
  1.2691 +    case NS_THEME_RANGE:
  1.2692 +    case NS_THEME_RANGE_THUMB:
  1.2693 +    case NS_THEME_GROUPBOX:
  1.2694 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.2695 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.2696 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.2697 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.2698 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.2699 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.2700 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.2701 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
  1.2702 +    case NS_THEME_SCROLLBAR_NON_DISAPPEARING:
  1.2703 +    case NS_THEME_SCALE_HORIZONTAL:
  1.2704 +    case NS_THEME_SCALE_VERTICAL:
  1.2705 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.2706 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.2707 +    case NS_THEME_DROPDOWN_BUTTON:
  1.2708 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.2709 +    case NS_THEME_SPINNER_DOWN_BUTTON:
  1.2710 +    case NS_THEME_LISTBOX:
  1.2711 +    case NS_THEME_TREEVIEW:
  1.2712 +    case NS_THEME_DROPDOWN_TEXTFIELD:
  1.2713 +    case NS_THEME_DROPDOWN:
  1.2714 +    case NS_THEME_TOOLTIP:
  1.2715 +    case NS_THEME_STATUSBAR:
  1.2716 +    case NS_THEME_STATUSBAR_PANEL:
  1.2717 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
  1.2718 +    case NS_THEME_PROGRESSBAR:
  1.2719 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2720 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.2721 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.2722 +    case NS_THEME_TAB:
  1.2723 +    case NS_THEME_TAB_PANEL:
  1.2724 +    case NS_THEME_TAB_PANELS:
  1.2725 +    case NS_THEME_MENUITEM:
  1.2726 +    case NS_THEME_CHECKMENUITEM:
  1.2727 +    case NS_THEME_RADIOMENUITEM:
  1.2728 +    case NS_THEME_MENUCHECKBOX:
  1.2729 +    case NS_THEME_MENURADIO:
  1.2730 +    case NS_THEME_MENUARROW:
  1.2731 +    case NS_THEME_MENUSEPARATOR:
  1.2732 +    case NS_THEME_MENUITEMTEXT:
  1.2733 +    case NS_THEME_WINDOW_TITLEBAR:
  1.2734 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.2735 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.2736 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.2737 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.2738 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.2739 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.2740 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.2741 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.2742 +    case NS_THEME_WINDOW_BUTTON_BOX:
  1.2743 +    case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
  1.2744 +      return true;
  1.2745 +  }
  1.2746 +  return false;
  1.2747 +}
  1.2748 +
  1.2749 +nsresult
  1.2750 +nsNativeThemeWin::ClassicGetWidgetBorder(nsDeviceContext* aContext, 
  1.2751 +                                  nsIFrame* aFrame,
  1.2752 +                                  uint8_t aWidgetType,
  1.2753 +                                  nsIntMargin* aResult)
  1.2754 +{
  1.2755 +  switch (aWidgetType) {
  1.2756 +    case NS_THEME_GROUPBOX:
  1.2757 +    case NS_THEME_BUTTON:
  1.2758 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 2; 
  1.2759 +      break;
  1.2760 +    case NS_THEME_STATUSBAR:
  1.2761 +      (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
  1.2762 +      (*aResult).top = 2;
  1.2763 +      break;
  1.2764 +    case NS_THEME_LISTBOX:
  1.2765 +    case NS_THEME_TREEVIEW:
  1.2766 +    case NS_THEME_DROPDOWN:
  1.2767 +    case NS_THEME_DROPDOWN_TEXTFIELD:
  1.2768 +    case NS_THEME_TAB:
  1.2769 +    case NS_THEME_NUMBER_INPUT:
  1.2770 +    case NS_THEME_TEXTFIELD:
  1.2771 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.2772 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 2;
  1.2773 +      break;
  1.2774 +    case NS_THEME_STATUSBAR_PANEL:
  1.2775 +    case NS_THEME_STATUSBAR_RESIZER_PANEL: {
  1.2776 +      (*aResult).top = 1;      
  1.2777 +      (*aResult).left = 1;
  1.2778 +      (*aResult).bottom = 1;
  1.2779 +      (*aResult).right = aFrame->GetNextSibling() ? 3 : 1;
  1.2780 +      break;
  1.2781 +    }    
  1.2782 +    case NS_THEME_TOOLTIP:
  1.2783 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
  1.2784 +      break;
  1.2785 +    case NS_THEME_PROGRESSBAR:
  1.2786 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2787 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
  1.2788 +      break;
  1.2789 +    case NS_THEME_MENUBAR:
  1.2790 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 0;
  1.2791 +      break;
  1.2792 +    case NS_THEME_MENUPOPUP:
  1.2793 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 3;
  1.2794 +      break;
  1.2795 +    default:
  1.2796 +      (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
  1.2797 +      break;
  1.2798 +  }
  1.2799 +  return NS_OK;
  1.2800 +}
  1.2801 +
  1.2802 +bool
  1.2803 +nsNativeThemeWin::ClassicGetWidgetPadding(nsDeviceContext* aContext,
  1.2804 +                                   nsIFrame* aFrame,
  1.2805 +                                   uint8_t aWidgetType,
  1.2806 +                                   nsIntMargin* aResult)
  1.2807 +{
  1.2808 +  switch (aWidgetType) {
  1.2809 +    case NS_THEME_MENUITEM:
  1.2810 +    case NS_THEME_CHECKMENUITEM:
  1.2811 +    case NS_THEME_RADIOMENUITEM: {
  1.2812 +      int32_t part, state;
  1.2813 +      bool focused;
  1.2814 +
  1.2815 +      if (NS_FAILED(ClassicGetThemePartAndState(aFrame, aWidgetType, part, state, focused)))
  1.2816 +        return false;
  1.2817 +
  1.2818 +      if (part == 1) { // top-level menu
  1.2819 +        if (nsUXThemeData::sFlatMenus || !(state & DFCS_PUSHED)) {
  1.2820 +          (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 2;
  1.2821 +        }
  1.2822 +        else {
  1.2823 +          // make top-level menus look sunken when pushed in the Classic look
  1.2824 +          (*aResult).top = (*aResult).left = 3;
  1.2825 +          (*aResult).bottom = (*aResult).right = 1;
  1.2826 +        }
  1.2827 +      }
  1.2828 +      else {
  1.2829 +        (*aResult).top = 0;
  1.2830 +        (*aResult).bottom = (*aResult).left = (*aResult).right = 2;
  1.2831 +      }
  1.2832 +      return true;
  1.2833 +    }
  1.2834 +    case NS_THEME_PROGRESSBAR:
  1.2835 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2836 +      (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
  1.2837 +      return true;
  1.2838 +    default:
  1.2839 +      return false;
  1.2840 +  }
  1.2841 +}
  1.2842 +
  1.2843 +nsresult
  1.2844 +nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* aFrame,
  1.2845 +                                       uint8_t aWidgetType,
  1.2846 +                                       nsIntSize* aResult, bool* aIsOverridable)
  1.2847 +{
  1.2848 +  (*aResult).width = (*aResult).height = 0;
  1.2849 +  *aIsOverridable = true;
  1.2850 +  switch (aWidgetType) {
  1.2851 +    case NS_THEME_RADIO:
  1.2852 +    case NS_THEME_CHECKBOX:
  1.2853 +      (*aResult).width = (*aResult).height = 13;
  1.2854 +      break;
  1.2855 +    case NS_THEME_MENUCHECKBOX:
  1.2856 +    case NS_THEME_MENURADIO:
  1.2857 +    case NS_THEME_MENUARROW:
  1.2858 +      (*aResult).width = ::GetSystemMetrics(SM_CXMENUCHECK);
  1.2859 +      (*aResult).height = ::GetSystemMetrics(SM_CYMENUCHECK);
  1.2860 +      break;
  1.2861 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.2862 +    case NS_THEME_SPINNER_DOWN_BUTTON:
  1.2863 +      (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
  1.2864 +      (*aResult).height = 8; // No good metrics available for this
  1.2865 +      *aIsOverridable = false;
  1.2866 +      break;
  1.2867 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.2868 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.2869 +      (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
  1.2870 +      (*aResult).height = ::GetSystemMetrics(SM_CYVSCROLL);
  1.2871 +      *aIsOverridable = false;
  1.2872 +      break;
  1.2873 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.2874 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.2875 +      (*aResult).width = ::GetSystemMetrics(SM_CXHSCROLL);
  1.2876 +      (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
  1.2877 +      *aIsOverridable = false;
  1.2878 +      break;
  1.2879 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.2880 +      // XXX HACK We should be able to have a minimum height for the scrollbar
  1.2881 +      // track.  However, this causes problems when uncollapsing a scrollbar
  1.2882 +      // inside a tree.  See bug 201379 for details.
  1.2883 +
  1.2884 +        //      (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB) << 1;
  1.2885 +      break;
  1.2886 +    case NS_THEME_SCROLLBAR_NON_DISAPPEARING:
  1.2887 +    {
  1.2888 +      aResult->SizeTo(::GetSystemMetrics(SM_CXHSCROLL),
  1.2889 +                      ::GetSystemMetrics(SM_CYVSCROLL));
  1.2890 +      break;
  1.2891 +    }
  1.2892 +    case NS_THEME_RANGE_THUMB: {
  1.2893 +      if (IsRangeHorizontal(aFrame)) {
  1.2894 +        (*aResult).width = 12;
  1.2895 +        (*aResult).height = 20;
  1.2896 +      } else {
  1.2897 +        (*aResult).width = 20;
  1.2898 +        (*aResult).height = 12;
  1.2899 +      }
  1.2900 +      *aIsOverridable = false;
  1.2901 +      break;
  1.2902 +    }
  1.2903 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.2904 +      (*aResult).width = 12;
  1.2905 +      (*aResult).height = 20;
  1.2906 +      *aIsOverridable = false;
  1.2907 +      break;
  1.2908 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.2909 +      (*aResult).width = 20;
  1.2910 +      (*aResult).height = 12;
  1.2911 +      *aIsOverridable = false;
  1.2912 +      break;
  1.2913 +    case NS_THEME_DROPDOWN_BUTTON:
  1.2914 +      (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
  1.2915 +      break;
  1.2916 +    case NS_THEME_DROPDOWN:
  1.2917 +    case NS_THEME_BUTTON:
  1.2918 +    case NS_THEME_GROUPBOX:
  1.2919 +    case NS_THEME_LISTBOX:
  1.2920 +    case NS_THEME_TREEVIEW:
  1.2921 +    case NS_THEME_NUMBER_INPUT:
  1.2922 +    case NS_THEME_TEXTFIELD:
  1.2923 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.2924 +    case NS_THEME_DROPDOWN_TEXTFIELD:      
  1.2925 +    case NS_THEME_STATUSBAR:
  1.2926 +    case NS_THEME_STATUSBAR_PANEL:      
  1.2927 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
  1.2928 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.2929 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.2930 +    case NS_THEME_TOOLTIP:
  1.2931 +    case NS_THEME_PROGRESSBAR:
  1.2932 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.2933 +    case NS_THEME_TAB:
  1.2934 +    case NS_THEME_TAB_PANEL:
  1.2935 +    case NS_THEME_TAB_PANELS:
  1.2936 +      // no minimum widget size
  1.2937 +      break;
  1.2938 +    case NS_THEME_RESIZER: {     
  1.2939 +      NONCLIENTMETRICS nc;
  1.2940 +      nc.cbSize = sizeof(nc);
  1.2941 +      if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nc), &nc, 0))
  1.2942 +        (*aResult).width = (*aResult).height = abs(nc.lfStatusFont.lfHeight) + 4;
  1.2943 +      else
  1.2944 +        (*aResult).width = (*aResult).height = 15;
  1.2945 +      *aIsOverridable = false;
  1.2946 +      break;
  1.2947 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.2948 +      (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
  1.2949 +      (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB);
  1.2950 +      // Without theming, divide the thumb size by two in order to look more
  1.2951 +      // native
  1.2952 +      if (!GetTheme(aWidgetType))
  1.2953 +        (*aResult).height >>= 1;
  1.2954 +      *aIsOverridable = false;
  1.2955 +      break;
  1.2956 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.2957 +      (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB);
  1.2958 +      (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
  1.2959 +      // Without theming, divide the thumb size by two in order to look more
  1.2960 +      // native
  1.2961 +      if (!GetTheme(aWidgetType))
  1.2962 +        (*aResult).width >>= 1;
  1.2963 +      *aIsOverridable = false;
  1.2964 +      break;
  1.2965 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
  1.2966 +      (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB) << 1;
  1.2967 +      break;
  1.2968 +    }
  1.2969 +    case NS_THEME_MENUSEPARATOR:
  1.2970 +    {
  1.2971 +      aResult->width = 0;
  1.2972 +      aResult->height = 10;
  1.2973 +      break;
  1.2974 +    }
  1.2975 +
  1.2976 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.2977 +    case NS_THEME_WINDOW_TITLEBAR:
  1.2978 +      aResult->height = GetSystemMetrics(SM_CYCAPTION);
  1.2979 +      aResult->height += GetSystemMetrics(SM_CYFRAME);
  1.2980 +      aResult->width = 0;
  1.2981 +    break;
  1.2982 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.2983 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.2984 +      aResult->width = GetSystemMetrics(SM_CXFRAME);
  1.2985 +      aResult->height = 0;
  1.2986 +    break;
  1.2987 +
  1.2988 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.2989 +      aResult->height = GetSystemMetrics(SM_CYFRAME);
  1.2990 +      aResult->width = 0;
  1.2991 +    break;
  1.2992 +
  1.2993 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.2994 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.2995 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.2996 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.2997 +      aResult->width = GetSystemMetrics(SM_CXSIZE);
  1.2998 +      aResult->height = GetSystemMetrics(SM_CYSIZE);
  1.2999 +      // XXX I have no idea why these caption metrics are always off,
  1.3000 +      // but they are.
  1.3001 +      aResult->width -= 2;
  1.3002 +      aResult->height -= 4;
  1.3003 +      if (aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE) {
  1.3004 +        AddPaddingRect(aResult, CAPTIONBUTTON_MINIMIZE);
  1.3005 +      }
  1.3006 +      else if (aWidgetType == NS_THEME_WINDOW_BUTTON_MAXIMIZE ||
  1.3007 +               aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
  1.3008 +        AddPaddingRect(aResult, CAPTIONBUTTON_RESTORE);
  1.3009 +      }
  1.3010 +      else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) {
  1.3011 +        AddPaddingRect(aResult, CAPTIONBUTTON_CLOSE);
  1.3012 +      }
  1.3013 +    break;
  1.3014 +
  1.3015 +    default:
  1.3016 +      return NS_ERROR_FAILURE;
  1.3017 +  }  
  1.3018 +  return NS_OK;
  1.3019 +}
  1.3020 +
  1.3021 +
  1.3022 +nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
  1.3023 +                                 int32_t& aPart, int32_t& aState, bool& aFocused)
  1.3024 +{  
  1.3025 +  aFocused = false;
  1.3026 +  switch (aWidgetType) {
  1.3027 +    case NS_THEME_BUTTON: {
  1.3028 +      EventStates contentState;
  1.3029 +
  1.3030 +      aPart = DFC_BUTTON;
  1.3031 +      aState = DFCS_BUTTONPUSH;
  1.3032 +      aFocused = false;
  1.3033 +
  1.3034 +      contentState = GetContentState(aFrame, aWidgetType);
  1.3035 +      if (IsDisabled(aFrame, contentState))
  1.3036 +        aState |= DFCS_INACTIVE;
  1.3037 +      else if (IsOpenButton(aFrame))
  1.3038 +        aState |= DFCS_PUSHED;
  1.3039 +      else if (IsCheckedButton(aFrame))
  1.3040 +        aState |= DFCS_CHECKED;
  1.3041 +      else {
  1.3042 +        if (contentState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)) {
  1.3043 +          aState |= DFCS_PUSHED;
  1.3044 +          const nsStyleUserInterface *uiData = aFrame->StyleUserInterface();
  1.3045 +          // The down state is flat if the button is focusable
  1.3046 +          if (uiData->mUserFocus == NS_STYLE_USER_FOCUS_NORMAL) {
  1.3047 +            if (!aFrame->GetContent()->IsHTML())
  1.3048 +              aState |= DFCS_FLAT;
  1.3049 +
  1.3050 +            aFocused = true;
  1.3051 +          }
  1.3052 +        }
  1.3053 +        if (contentState.HasState(NS_EVENT_STATE_FOCUS) ||
  1.3054 +            (aState == DFCS_BUTTONPUSH && IsDefaultButton(aFrame))) {
  1.3055 +          aFocused = true;
  1.3056 +        }
  1.3057 +
  1.3058 +      }
  1.3059 +
  1.3060 +      return NS_OK;
  1.3061 +    }
  1.3062 +    case NS_THEME_CHECKBOX:
  1.3063 +    case NS_THEME_RADIO: {
  1.3064 +      EventStates contentState;
  1.3065 +      aFocused = false;
  1.3066 +
  1.3067 +      aPart = DFC_BUTTON;
  1.3068 +      aState = 0;
  1.3069 +      nsIContent* content = aFrame->GetContent();
  1.3070 +      bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
  1.3071 +      bool isChecked = GetCheckedOrSelected(aFrame, !isCheckbox);
  1.3072 +      bool isIndeterminate = isCheckbox && GetIndeterminate(aFrame);
  1.3073 +
  1.3074 +      if (isCheckbox) {
  1.3075 +        // indeterminate state takes precedence over checkedness.
  1.3076 +        if (isIndeterminate) {
  1.3077 +          aState = DFCS_BUTTON3STATE | DFCS_CHECKED;
  1.3078 +        } else {
  1.3079 +          aState = DFCS_BUTTONCHECK;
  1.3080 +        }
  1.3081 +      } else {
  1.3082 +        aState = DFCS_BUTTONRADIO;
  1.3083 +      }
  1.3084 +      if (isChecked) {
  1.3085 +        aState |= DFCS_CHECKED;
  1.3086 +      }
  1.3087 +
  1.3088 +      contentState = GetContentState(aFrame, aWidgetType);
  1.3089 +      if (!content->IsXUL() &&
  1.3090 +          contentState.HasState(NS_EVENT_STATE_FOCUS)) {
  1.3091 +        aFocused = true;
  1.3092 +      }
  1.3093 +
  1.3094 +      if (IsDisabled(aFrame, contentState)) {
  1.3095 +        aState |= DFCS_INACTIVE;
  1.3096 +      } else if (contentState.HasAllStates(NS_EVENT_STATE_ACTIVE |
  1.3097 +                                           NS_EVENT_STATE_HOVER)) {
  1.3098 +        aState |= DFCS_PUSHED;
  1.3099 +      }
  1.3100 +
  1.3101 +      return NS_OK;
  1.3102 +    }
  1.3103 +    case NS_THEME_MENUITEM:
  1.3104 +    case NS_THEME_CHECKMENUITEM:
  1.3105 +    case NS_THEME_RADIOMENUITEM: {
  1.3106 +      bool isTopLevel = false;
  1.3107 +      bool isOpen = false;
  1.3108 +      bool isContainer = false;
  1.3109 +      nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
  1.3110 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.3111 +
  1.3112 +      // We indicate top-level-ness using aPart. 0 is a normal menu item,
  1.3113 +      // 1 is a top-level menu item. The state of the item is composed of
  1.3114 +      // DFCS_* flags only.
  1.3115 +      aPart = 0;
  1.3116 +      aState = 0;
  1.3117 +
  1.3118 +      if (menuFrame) {
  1.3119 +        // If this is a real menu item, we should check if it is part of the
  1.3120 +        // main menu bar or not, and if it is a container, as these affect
  1.3121 +        // rendering.
  1.3122 +        isTopLevel = menuFrame->IsOnMenuBar();
  1.3123 +        isOpen = menuFrame->IsOpen();
  1.3124 +        isContainer = menuFrame->IsMenu();
  1.3125 +      }
  1.3126 +
  1.3127 +      if (IsDisabled(aFrame, eventState))
  1.3128 +        aState |= DFCS_INACTIVE;
  1.3129 +
  1.3130 +      if (isTopLevel) {
  1.3131 +        aPart = 1;
  1.3132 +        if (isOpen)
  1.3133 +          aState |= DFCS_PUSHED;
  1.3134 +      }
  1.3135 +
  1.3136 +      if (IsMenuActive(aFrame, aWidgetType))
  1.3137 +        aState |= DFCS_HOT;
  1.3138 +
  1.3139 +      return NS_OK;
  1.3140 +    }
  1.3141 +    case NS_THEME_MENUCHECKBOX:
  1.3142 +    case NS_THEME_MENURADIO:
  1.3143 +    case NS_THEME_MENUARROW: {
  1.3144 +      aState = 0;
  1.3145 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.3146 +
  1.3147 +      if (IsDisabled(aFrame, eventState))
  1.3148 +        aState |= DFCS_INACTIVE;
  1.3149 +      if (IsMenuActive(aFrame, aWidgetType))
  1.3150 +        aState |= DFCS_HOT;
  1.3151 +
  1.3152 +      if (aWidgetType == NS_THEME_MENUCHECKBOX || aWidgetType == NS_THEME_MENURADIO) {
  1.3153 +        if (IsCheckedButton(aFrame))
  1.3154 +          aState |= DFCS_CHECKED;
  1.3155 +      } else if (IsFrameRTL(aFrame)) {
  1.3156 +          aState |= DFCS_RTL;
  1.3157 +      }
  1.3158 +      return NS_OK;
  1.3159 +    }
  1.3160 +    case NS_THEME_LISTBOX:
  1.3161 +    case NS_THEME_TREEVIEW:
  1.3162 +    case NS_THEME_NUMBER_INPUT:
  1.3163 +    case NS_THEME_TEXTFIELD:
  1.3164 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.3165 +    case NS_THEME_DROPDOWN:
  1.3166 +    case NS_THEME_DROPDOWN_TEXTFIELD:
  1.3167 +    case NS_THEME_RANGE:
  1.3168 +    case NS_THEME_RANGE_THUMB:
  1.3169 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.3170 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:     
  1.3171 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.3172 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:      
  1.3173 +    case NS_THEME_SCALE_HORIZONTAL:
  1.3174 +    case NS_THEME_SCALE_VERTICAL:
  1.3175 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.3176 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.3177 +    case NS_THEME_STATUSBAR:
  1.3178 +    case NS_THEME_STATUSBAR_PANEL:
  1.3179 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
  1.3180 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.3181 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.3182 +    case NS_THEME_TOOLTIP:
  1.3183 +    case NS_THEME_PROGRESSBAR:
  1.3184 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.3185 +    case NS_THEME_TAB:
  1.3186 +    case NS_THEME_TAB_PANEL:
  1.3187 +    case NS_THEME_TAB_PANELS:
  1.3188 +    case NS_THEME_MENUBAR:
  1.3189 +    case NS_THEME_MENUPOPUP:
  1.3190 +    case NS_THEME_GROUPBOX:
  1.3191 +      // these don't use DrawFrameControl
  1.3192 +      return NS_OK;
  1.3193 +    case NS_THEME_DROPDOWN_BUTTON: {
  1.3194 +
  1.3195 +      aPart = DFC_SCROLL;
  1.3196 +      aState = DFCS_SCROLLCOMBOBOX;
  1.3197 +
  1.3198 +      nsIFrame* parentFrame = aFrame->GetParent();
  1.3199 +      bool isHTML = IsHTMLContent(aFrame);
  1.3200 +      bool isMenulist = !isHTML && parentFrame->GetType() == nsGkAtoms::menuFrame;
  1.3201 +      bool isOpen = false;
  1.3202 +
  1.3203 +      // HTML select and XUL menulist dropdown buttons get state from the parent.
  1.3204 +      if (isHTML || isMenulist)
  1.3205 +        aFrame = parentFrame;
  1.3206 +
  1.3207 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.3208 +
  1.3209 +      if (IsDisabled(aFrame, eventState)) {
  1.3210 +        aState |= DFCS_INACTIVE;
  1.3211 +        return NS_OK;
  1.3212 +      }
  1.3213 +
  1.3214 +      if (isHTML) {
  1.3215 +        nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
  1.3216 +        isOpen = (ccf && ccf->IsDroppedDown());
  1.3217 +      }
  1.3218 +      else
  1.3219 +        isOpen = IsOpenButton(aFrame);
  1.3220 +
  1.3221 +      // XXX Button should look active until the mouse is released, but
  1.3222 +      //     without making it look active when the popup is clicked.
  1.3223 +      if (isOpen && (isHTML || isMenulist))
  1.3224 +        return NS_OK;
  1.3225 +
  1.3226 +      // Dropdown button active state doesn't need :hover.
  1.3227 +      if (eventState.HasState(NS_EVENT_STATE_ACTIVE))
  1.3228 +        aState |= DFCS_PUSHED | DFCS_FLAT;
  1.3229 +
  1.3230 +      return NS_OK;
  1.3231 +    }
  1.3232 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.3233 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.3234 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.3235 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
  1.3236 +      EventStates contentState = GetContentState(aFrame, aWidgetType);
  1.3237 +
  1.3238 +      aPart = DFC_SCROLL;
  1.3239 +      switch (aWidgetType) {
  1.3240 +        case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.3241 +          aState = DFCS_SCROLLUP;
  1.3242 +          break;
  1.3243 +        case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.3244 +          aState = DFCS_SCROLLDOWN;
  1.3245 +          break;
  1.3246 +        case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.3247 +          aState = DFCS_SCROLLLEFT;
  1.3248 +          break;
  1.3249 +        case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.3250 +          aState = DFCS_SCROLLRIGHT;
  1.3251 +          break;
  1.3252 +      }
  1.3253 +
  1.3254 +      if (IsDisabled(aFrame, contentState))
  1.3255 +        aState |= DFCS_INACTIVE;
  1.3256 +      else {
  1.3257 +        if (contentState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
  1.3258 +          aState |= DFCS_PUSHED | DFCS_FLAT;
  1.3259 +      }
  1.3260 +
  1.3261 +      return NS_OK;
  1.3262 +    }
  1.3263 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.3264 +    case NS_THEME_SPINNER_DOWN_BUTTON: {
  1.3265 +      EventStates contentState = GetContentState(aFrame, aWidgetType);
  1.3266 +
  1.3267 +      aPart = DFC_SCROLL;
  1.3268 +      switch (aWidgetType) {
  1.3269 +        case NS_THEME_SPINNER_UP_BUTTON:
  1.3270 +          aState = DFCS_SCROLLUP;
  1.3271 +          break;
  1.3272 +        case NS_THEME_SPINNER_DOWN_BUTTON:
  1.3273 +          aState = DFCS_SCROLLDOWN;
  1.3274 +          break;
  1.3275 +      }
  1.3276 +
  1.3277 +      if (IsDisabled(aFrame, contentState))
  1.3278 +        aState |= DFCS_INACTIVE;
  1.3279 +      else {
  1.3280 +        if (contentState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
  1.3281 +          aState |= DFCS_PUSHED;
  1.3282 +      }
  1.3283 +
  1.3284 +      return NS_OK;    
  1.3285 +    }
  1.3286 +    case NS_THEME_RESIZER:    
  1.3287 +      aPart = DFC_SCROLL;
  1.3288 +      aState = (IsFrameRTL(aFrame)) ?
  1.3289 +               DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP;
  1.3290 +      return NS_OK;
  1.3291 +    case NS_THEME_MENUSEPARATOR:
  1.3292 +      aPart = 0;
  1.3293 +      aState = 0;
  1.3294 +      return NS_OK;
  1.3295 +    case NS_THEME_WINDOW_TITLEBAR:
  1.3296 +      aPart = mozilla::widget::themeconst::WP_CAPTION;
  1.3297 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.3298 +      return NS_OK;
  1.3299 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.3300 +      aPart = mozilla::widget::themeconst::WP_MAXCAPTION;
  1.3301 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.3302 +      return NS_OK;
  1.3303 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.3304 +      aPart = mozilla::widget::themeconst::WP_FRAMELEFT;
  1.3305 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.3306 +      return NS_OK;
  1.3307 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.3308 +      aPart = mozilla::widget::themeconst::WP_FRAMERIGHT;
  1.3309 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.3310 +      return NS_OK;
  1.3311 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.3312 +      aPart = mozilla::widget::themeconst::WP_FRAMEBOTTOM;
  1.3313 +      aState = GetTopLevelWindowActiveState(aFrame);
  1.3314 +      return NS_OK;
  1.3315 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.3316 +      aPart = DFC_CAPTION;
  1.3317 +      aState = DFCS_CAPTIONCLOSE |
  1.3318 +               GetClassicWindowFrameButtonState(GetContentState(aFrame,
  1.3319 +                                                                aWidgetType));
  1.3320 +      return NS_OK;
  1.3321 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.3322 +      aPart = DFC_CAPTION;
  1.3323 +      aState = DFCS_CAPTIONMIN |
  1.3324 +               GetClassicWindowFrameButtonState(GetContentState(aFrame,
  1.3325 +                                                                aWidgetType));
  1.3326 +      return NS_OK;
  1.3327 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.3328 +      aPart = DFC_CAPTION;
  1.3329 +      aState = DFCS_CAPTIONMAX |
  1.3330 +               GetClassicWindowFrameButtonState(GetContentState(aFrame,
  1.3331 +                                                                aWidgetType));
  1.3332 +      return NS_OK;
  1.3333 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.3334 +      aPart = DFC_CAPTION;
  1.3335 +      aState = DFCS_CAPTIONRESTORE |
  1.3336 +               GetClassicWindowFrameButtonState(GetContentState(aFrame,
  1.3337 +                                                                aWidgetType));
  1.3338 +      return NS_OK;
  1.3339 +  }
  1.3340 +  return NS_ERROR_FAILURE;
  1.3341 +}
  1.3342 +
  1.3343 +// Draw classic Windows tab
  1.3344 +// (no system API for this, but DrawEdge can draw all the parts of a tab)
  1.3345 +static void DrawTab(HDC hdc, const RECT& R, int32_t aPosition, bool aSelected,
  1.3346 +                    bool aDrawLeft, bool aDrawRight)
  1.3347 +{
  1.3348 +  int32_t leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;  
  1.3349 +  RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
  1.3350 +  int32_t selectedOffset, lOffset, rOffset;
  1.3351 +
  1.3352 +  selectedOffset = aSelected ? 1 : 0;
  1.3353 +  lOffset = aDrawLeft ? 2 : 0;
  1.3354 +  rOffset = aDrawRight ? 2 : 0;
  1.3355 +
  1.3356 +  // Get info for tab orientation/position (Left, Top, Right, Bottom)
  1.3357 +  switch (aPosition) {
  1.3358 +    case BF_LEFT:
  1.3359 +      leftFlag = BF_TOP; topFlag = BF_LEFT;
  1.3360 +      rightFlag = BF_BOTTOM;
  1.3361 +      lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
  1.3362 +      shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
  1.3363 +
  1.3364 +      ::SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
  1.3365 +      ::SetRect(&sideRect, R.left+2, R.top, R.right-2+selectedOffset, R.bottom);
  1.3366 +      ::SetRect(&bottomRect, R.right-2, R.top, R.right, R.bottom);
  1.3367 +      ::SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
  1.3368 +      ::SetRect(&shadeRect, R.left+1, R.bottom-2, R.left+2, R.bottom-1);
  1.3369 +      break;
  1.3370 +    case BF_TOP:    
  1.3371 +      leftFlag = BF_LEFT; topFlag = BF_TOP;
  1.3372 +      rightFlag = BF_RIGHT;
  1.3373 +      lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
  1.3374 +      shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
  1.3375 +
  1.3376 +      ::SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
  1.3377 +      ::SetRect(&sideRect, R.left, R.top+2, R.right, R.bottom-1+selectedOffset);
  1.3378 +      ::SetRect(&bottomRect, R.left, R.bottom-1, R.right, R.bottom);
  1.3379 +      ::SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);      
  1.3380 +      ::SetRect(&shadeRect, R.right-2, R.top+1, R.right-1, R.top+2);      
  1.3381 +      break;
  1.3382 +    case BF_RIGHT:    
  1.3383 +      leftFlag = BF_TOP; topFlag = BF_RIGHT;
  1.3384 +      rightFlag = BF_BOTTOM;
  1.3385 +      lightFlag = BF_DIAGONAL_ENDTOPLEFT;
  1.3386 +      shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
  1.3387 +
  1.3388 +      ::SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
  1.3389 +      ::SetRect(&sideRect, R.left+2-selectedOffset, R.top, R.right-2, R.bottom);
  1.3390 +      ::SetRect(&bottomRect, R.left, R.top, R.left+2, R.bottom);
  1.3391 +      ::SetRect(&lightRect, R.right-3, R.top, R.right-1, R.top+2);
  1.3392 +      ::SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
  1.3393 +      break;
  1.3394 +    case BF_BOTTOM:    
  1.3395 +      leftFlag = BF_LEFT; topFlag = BF_BOTTOM;
  1.3396 +      rightFlag = BF_RIGHT;
  1.3397 +      lightFlag = BF_DIAGONAL_ENDTOPLEFT;
  1.3398 +      shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
  1.3399 +
  1.3400 +      ::SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
  1.3401 +      ::SetRect(&sideRect, R.left, R.top+2-selectedOffset, R.right, R.bottom-2);
  1.3402 +      ::SetRect(&bottomRect, R.left, R.top, R.right, R.top+2);
  1.3403 +      ::SetRect(&lightRect, R.left, R.bottom-3, R.left+2, R.bottom-1);
  1.3404 +      ::SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
  1.3405 +      break;
  1.3406 +  }
  1.3407 +
  1.3408 +  // Background
  1.3409 +  ::FillRect(hdc, &R, (HBRUSH) (COLOR_3DFACE+1) );
  1.3410 +
  1.3411 +  // Tab "Top"
  1.3412 +  ::DrawEdge(hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
  1.3413 +
  1.3414 +  // Tab "Bottom"
  1.3415 +  if (!aSelected)
  1.3416 +    ::DrawEdge(hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
  1.3417 +
  1.3418 +  // Tab "Sides"
  1.3419 +  if (!aDrawLeft)
  1.3420 +    leftFlag = 0;
  1.3421 +  if (!aDrawRight)
  1.3422 +    rightFlag = 0;
  1.3423 +  ::DrawEdge(hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
  1.3424 +
  1.3425 +  // Tab Diagonal Corners
  1.3426 +  if (aDrawLeft)
  1.3427 +    ::DrawEdge(hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
  1.3428 +
  1.3429 +  if (aDrawRight)
  1.3430 +    ::DrawEdge(hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
  1.3431 +}
  1.3432 +
  1.3433 +static void DrawMenuImage(HDC hdc, const RECT& rc, int32_t aComponent, uint32_t aColor)
  1.3434 +{
  1.3435 +  // This procedure creates a memory bitmap to contain the check mark, draws
  1.3436 +  // it into the bitmap (it is a mask image), then composes it onto the menu
  1.3437 +  // item in appropriate colors.
  1.3438 +  HDC hMemoryDC = ::CreateCompatibleDC(hdc);
  1.3439 +  if (hMemoryDC) {
  1.3440 +    // XXXjgr We should ideally be caching these, but we wont be notified when
  1.3441 +    // they change currently, so we can't do so easily. Same for the bitmap.
  1.3442 +    int checkW = ::GetSystemMetrics(SM_CXMENUCHECK);
  1.3443 +    int checkH = ::GetSystemMetrics(SM_CYMENUCHECK);
  1.3444 +
  1.3445 +    HBITMAP hMonoBitmap = ::CreateBitmap(checkW, checkH, 1, 1, nullptr);
  1.3446 +    if (hMonoBitmap) {
  1.3447 +
  1.3448 +      HBITMAP hPrevBitmap = (HBITMAP) ::SelectObject(hMemoryDC, hMonoBitmap);
  1.3449 +      if (hPrevBitmap) {
  1.3450 +
  1.3451 +        // XXXjgr This will go pear-shaped if the image is bigger than the
  1.3452 +        // provided rect. What should we do?
  1.3453 +        RECT imgRect = { 0, 0, checkW, checkH };
  1.3454 +        POINT imgPos = {
  1.3455 +              rc.left + (rc.right  - rc.left - checkW) / 2,
  1.3456 +              rc.top  + (rc.bottom - rc.top  - checkH) / 2
  1.3457 +            };
  1.3458 +
  1.3459 +        // XXXzeniko Windows renders these 1px lower than you'd expect
  1.3460 +        if (aComponent == DFCS_MENUCHECK || aComponent == DFCS_MENUBULLET)
  1.3461 +          imgPos.y++;
  1.3462 +
  1.3463 +        ::DrawFrameControl(hMemoryDC, &imgRect, DFC_MENU, aComponent);
  1.3464 +        COLORREF oldTextCol = ::SetTextColor(hdc, 0x00000000);
  1.3465 +        COLORREF oldBackCol = ::SetBkColor(hdc, 0x00FFFFFF);
  1.3466 +        ::BitBlt(hdc, imgPos.x, imgPos.y, checkW, checkH, hMemoryDC, 0, 0, SRCAND);
  1.3467 +        ::SetTextColor(hdc, ::GetSysColor(aColor));
  1.3468 +        ::SetBkColor(hdc, 0x00000000);
  1.3469 +        ::BitBlt(hdc, imgPos.x, imgPos.y, checkW, checkH, hMemoryDC, 0, 0, SRCPAINT);
  1.3470 +        ::SetTextColor(hdc, oldTextCol);
  1.3471 +        ::SetBkColor(hdc, oldBackCol);
  1.3472 +        ::SelectObject(hMemoryDC, hPrevBitmap);
  1.3473 +      }
  1.3474 +      ::DeleteObject(hMonoBitmap);
  1.3475 +    }
  1.3476 +    ::DeleteDC(hMemoryDC);
  1.3477 +  }
  1.3478 +}
  1.3479 +
  1.3480 +void nsNativeThemeWin::DrawCheckedRect(HDC hdc, const RECT& rc, int32_t fore, int32_t back,
  1.3481 +                                       HBRUSH defaultBack)
  1.3482 +{
  1.3483 +  static WORD patBits[8] = {
  1.3484 +    0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
  1.3485 +  };
  1.3486 +        
  1.3487 +  HBITMAP patBmp = ::CreateBitmap(8, 8, 1, 1, patBits);
  1.3488 +  if (patBmp) {
  1.3489 +    HBRUSH brush = (HBRUSH) ::CreatePatternBrush(patBmp);
  1.3490 +    if (brush) {        
  1.3491 +      COLORREF oldForeColor = ::SetTextColor(hdc, ::GetSysColor(fore));
  1.3492 +      COLORREF oldBackColor = ::SetBkColor(hdc, ::GetSysColor(back));
  1.3493 +      POINT vpOrg;
  1.3494 +
  1.3495 +      ::UnrealizeObject(brush);
  1.3496 +      ::GetViewportOrgEx(hdc, &vpOrg);
  1.3497 +      ::SetBrushOrgEx(hdc, vpOrg.x + rc.left, vpOrg.y + rc.top, nullptr);
  1.3498 +      HBRUSH oldBrush = (HBRUSH) ::SelectObject(hdc, brush);
  1.3499 +      ::FillRect(hdc, &rc, brush);
  1.3500 +      ::SetTextColor(hdc, oldForeColor);
  1.3501 +      ::SetBkColor(hdc, oldBackColor);
  1.3502 +      ::SelectObject(hdc, oldBrush);
  1.3503 +      ::DeleteObject(brush);          
  1.3504 +    }
  1.3505 +    else
  1.3506 +      ::FillRect(hdc, &rc, defaultBack);
  1.3507 +  
  1.3508 +    ::DeleteObject(patBmp);
  1.3509 +  }
  1.3510 +}
  1.3511 +
  1.3512 +nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsRenderingContext* aContext,
  1.3513 +                                  nsIFrame* aFrame,
  1.3514 +                                  uint8_t aWidgetType,
  1.3515 +                                  const nsRect& aRect,
  1.3516 +                                  const nsRect& aDirtyRect)
  1.3517 +{
  1.3518 +  int32_t part, state;
  1.3519 +  bool focused;
  1.3520 +  nsresult rv;
  1.3521 +  rv = ClassicGetThemePartAndState(aFrame, aWidgetType, part, state, focused);
  1.3522 +  if (NS_FAILED(rv))
  1.3523 +    return rv;
  1.3524 +
  1.3525 +  if (AssumeThemePartAndStateAreTransparent(part, state)) {
  1.3526 +    return NS_OK;
  1.3527 +  }
  1.3528 +
  1.3529 +  gfxFloat p2a = gfxFloat(aContext->AppUnitsPerDevPixel());
  1.3530 +  RECT widgetRect;
  1.3531 +  gfxRect tr(aRect.x, aRect.y, aRect.width, aRect.height),
  1.3532 +          dr(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
  1.3533 +
  1.3534 +  tr.ScaleInverse(p2a);
  1.3535 +  dr.ScaleInverse(p2a);
  1.3536 +
  1.3537 +  nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
  1.3538 +
  1.3539 +  gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
  1.3540 +
  1.3541 +RENDER_AGAIN:
  1.3542 +
  1.3543 +  HDC hdc = nativeDrawing.BeginNativeDrawing();
  1.3544 +  if (!hdc)
  1.3545 +    return NS_ERROR_FAILURE;
  1.3546 +
  1.3547 +  nativeDrawing.TransformToNativeRect(tr, widgetRect);
  1.3548 +
  1.3549 +  rv = NS_OK;
  1.3550 +  switch (aWidgetType) { 
  1.3551 +    // Draw button
  1.3552 +    case NS_THEME_BUTTON: {
  1.3553 +      if (focused) {
  1.3554 +        // draw dark button focus border first
  1.3555 +        HBRUSH brush;        
  1.3556 +        brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
  1.3557 +        if (brush)
  1.3558 +          ::FrameRect(hdc, &widgetRect, brush);
  1.3559 +        InflateRect(&widgetRect, -1, -1);
  1.3560 +      }
  1.3561 +      // fall-through...
  1.3562 +    }
  1.3563 +    // Draw controls supported by DrawFrameControl
  1.3564 +    case NS_THEME_CHECKBOX:
  1.3565 +    case NS_THEME_RADIO:
  1.3566 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.3567 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.3568 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.3569 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.3570 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.3571 +    case NS_THEME_SPINNER_DOWN_BUTTON:
  1.3572 +    case NS_THEME_DROPDOWN_BUTTON:
  1.3573 +    case NS_THEME_RESIZER: {
  1.3574 +      int32_t oldTA;
  1.3575 +      // setup DC to make DrawFrameControl draw correctly
  1.3576 +      oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
  1.3577 +      ::DrawFrameControl(hdc, &widgetRect, part, state);
  1.3578 +      ::SetTextAlign(hdc, oldTA);
  1.3579 +
  1.3580 +      // Draw focus rectangles for HTML checkboxes and radio buttons
  1.3581 +      // XXX it'd be nice to draw these outside of the frame
  1.3582 +      if (focused && (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO)) {
  1.3583 +        // setup DC to make DrawFocusRect draw correctly
  1.3584 +        POINT vpOrg;
  1.3585 +        ::GetViewportOrgEx(hdc, &vpOrg);
  1.3586 +        ::SetBrushOrgEx(hdc, vpOrg.x + widgetRect.left, vpOrg.y + widgetRect.top, nullptr);
  1.3587 +        int32_t oldColor;
  1.3588 +        oldColor = ::SetTextColor(hdc, 0);
  1.3589 +        // draw focus rectangle
  1.3590 +        ::DrawFocusRect(hdc, &widgetRect);
  1.3591 +        ::SetTextColor(hdc, oldColor);
  1.3592 +      }
  1.3593 +      break;
  1.3594 +    }
  1.3595 +    // Draw controls with 2px 3D inset border
  1.3596 +    case NS_THEME_NUMBER_INPUT:
  1.3597 +    case NS_THEME_TEXTFIELD:
  1.3598 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.3599 +    case NS_THEME_LISTBOX:
  1.3600 +    case NS_THEME_DROPDOWN:
  1.3601 +    case NS_THEME_DROPDOWN_TEXTFIELD: {
  1.3602 +      // Draw inset edge
  1.3603 +      ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  1.3604 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.3605 +
  1.3606 +      // Fill in background
  1.3607 +      if (IsDisabled(aFrame, eventState) ||
  1.3608 +          (aFrame->GetContent()->IsXUL() &&
  1.3609 +           IsReadOnly(aFrame)))
  1.3610 +        ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1));
  1.3611 +      else
  1.3612 +        ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1));
  1.3613 +
  1.3614 +      break;
  1.3615 +    }
  1.3616 +    case NS_THEME_TREEVIEW: {
  1.3617 +      // Draw inset edge
  1.3618 +      ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  1.3619 +
  1.3620 +      // Fill in window color background
  1.3621 +      ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1));
  1.3622 +
  1.3623 +      break;
  1.3624 +    }
  1.3625 +    // Draw ToolTip background
  1.3626 +    case NS_THEME_TOOLTIP:
  1.3627 +      ::FrameRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_WINDOWFRAME));
  1.3628 +      InflateRect(&widgetRect, -1, -1);
  1.3629 +      ::FillRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_INFOBK));
  1.3630 +
  1.3631 +      break;
  1.3632 +    case NS_THEME_GROUPBOX:
  1.3633 +      ::DrawEdge(hdc, &widgetRect, EDGE_ETCHED, BF_RECT | BF_ADJUST);
  1.3634 +      ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1));
  1.3635 +      break;
  1.3636 +    // Draw 3D face background controls
  1.3637 +    case NS_THEME_PROGRESSBAR:
  1.3638 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.3639 +      // Draw 3D border
  1.3640 +      ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
  1.3641 +      InflateRect(&widgetRect, -1, -1);
  1.3642 +      // fall through
  1.3643 +    case NS_THEME_TAB_PANEL:
  1.3644 +    case NS_THEME_STATUSBAR:
  1.3645 +    case NS_THEME_STATUSBAR_RESIZER_PANEL: {
  1.3646 +      ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1));
  1.3647 +
  1.3648 +      break;
  1.3649 +    }
  1.3650 +    // Draw 3D inset statusbar panel
  1.3651 +    case NS_THEME_STATUSBAR_PANEL: {
  1.3652 +      if (aFrame->GetNextSibling())
  1.3653 +        widgetRect.right -= 2; // space between sibling status panels
  1.3654 +
  1.3655 +      ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
  1.3656 +
  1.3657 +      break;
  1.3658 +    }
  1.3659 +    // Draw scrollbar thumb
  1.3660 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.3661 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.3662 +      ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
  1.3663 +
  1.3664 +      break;
  1.3665 +    case NS_THEME_RANGE_THUMB:
  1.3666 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.3667 +    case NS_THEME_SCALE_THUMB_HORIZONTAL: {
  1.3668 +      EventStates eventState = GetContentState(aFrame, aWidgetType);
  1.3669 +
  1.3670 +      ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
  1.3671 +      if (IsDisabled(aFrame, eventState)) {
  1.3672 +        DrawCheckedRect(hdc, widgetRect, COLOR_3DFACE, COLOR_3DHILIGHT,
  1.3673 +                        (HBRUSH) COLOR_3DHILIGHT);
  1.3674 +      }
  1.3675 +
  1.3676 +      break;
  1.3677 +    }
  1.3678 +    // Draw scrollbar track background
  1.3679 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.3680 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: {
  1.3681 +
  1.3682 +      // Windows fills in the scrollbar track differently 
  1.3683 +      // depending on whether these are equal
  1.3684 +      DWORD color3D, colorScrollbar, colorWindow;
  1.3685 +
  1.3686 +      color3D = ::GetSysColor(COLOR_3DFACE);      
  1.3687 +      colorWindow = ::GetSysColor(COLOR_WINDOW);
  1.3688 +      colorScrollbar = ::GetSysColor(COLOR_SCROLLBAR);
  1.3689 +      
  1.3690 +      if ((color3D != colorScrollbar) && (colorWindow != colorScrollbar))
  1.3691 +        // Use solid brush
  1.3692 +        ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_SCROLLBAR+1));
  1.3693 +      else
  1.3694 +      {
  1.3695 +        DrawCheckedRect(hdc, widgetRect, COLOR_3DHILIGHT, COLOR_3DFACE,
  1.3696 +                        (HBRUSH) COLOR_SCROLLBAR+1);
  1.3697 +      }
  1.3698 +      // XXX should invert the part of the track being clicked here
  1.3699 +      // but the track is never :active
  1.3700 +
  1.3701 +      break;
  1.3702 +    }
  1.3703 +    // Draw scale track background
  1.3704 +    case NS_THEME_RANGE:
  1.3705 +    case NS_THEME_SCALE_VERTICAL:
  1.3706 +    case NS_THEME_SCALE_HORIZONTAL: { 
  1.3707 +      const int32_t trackWidth = 4;
  1.3708 +      // When rounding is necessary, we round the position of the track
  1.3709 +      // away from the chevron of the thumb to make it look better.
  1.3710 +      if (aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
  1.3711 +          (aWidgetType == NS_THEME_RANGE && IsRangeHorizontal(aFrame))) {
  1.3712 +        widgetRect.top += (widgetRect.bottom - widgetRect.top - trackWidth) / 2;
  1.3713 +        widgetRect.bottom = widgetRect.top + trackWidth;
  1.3714 +      }
  1.3715 +      else {
  1.3716 +        if (!IsFrameRTL(aFrame)) {
  1.3717 +          widgetRect.left += (widgetRect.right - widgetRect.left - trackWidth) / 2;
  1.3718 +          widgetRect.right = widgetRect.left + trackWidth;
  1.3719 +        } else {
  1.3720 +          widgetRect.right -= (widgetRect.right - widgetRect.left - trackWidth) / 2;
  1.3721 +          widgetRect.left = widgetRect.right - trackWidth;
  1.3722 +        }
  1.3723 +      }
  1.3724 +
  1.3725 +      ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  1.3726 +      ::FillRect(hdc, &widgetRect, (HBRUSH) GetStockObject(GRAY_BRUSH));
  1.3727 + 
  1.3728 +      break;
  1.3729 +    }
  1.3730 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.3731 +      ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
  1.3732 +      break;
  1.3733 +
  1.3734 +    case NS_THEME_PROGRESSBAR_CHUNK: {
  1.3735 +      nsIFrame* stateFrame = aFrame->GetParent();
  1.3736 +      EventStates eventStates = GetContentState(stateFrame, aWidgetType);
  1.3737 +
  1.3738 +      bool indeterminate = IsIndeterminateProgress(stateFrame, eventStates);
  1.3739 +      bool vertical = IsVerticalProgress(stateFrame) ||
  1.3740 +                      aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL;
  1.3741 +      int32_t overlayPart = GetProgressOverlayStyle(vertical);
  1.3742 +
  1.3743 +      nsIContent* content = aFrame->GetContent();
  1.3744 +      if (!indeterminate || !content) {
  1.3745 +        ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
  1.3746 +        break;
  1.3747 +      }
  1.3748 +
  1.3749 +      RECT overlayRect =
  1.3750 +        CalculateProgressOverlayRect(aFrame, &widgetRect, vertical,
  1.3751 +                                     indeterminate, true);
  1.3752 +
  1.3753 +      ::FillRect(hdc, &overlayRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
  1.3754 +
  1.3755 +      if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
  1.3756 +        NS_WARNING("unable to animate progress widget!");
  1.3757 +      }
  1.3758 +      break;
  1.3759 +    }
  1.3760 +
  1.3761 +    // Draw Tab
  1.3762 +    case NS_THEME_TAB: {
  1.3763 +      DrawTab(hdc, widgetRect,
  1.3764 +        IsBottomTab(aFrame) ? BF_BOTTOM : BF_TOP, 
  1.3765 +        IsSelectedTab(aFrame),
  1.3766 +        !IsRightToSelectedTab(aFrame),
  1.3767 +        !IsLeftToSelectedTab(aFrame));
  1.3768 +
  1.3769 +      break;
  1.3770 +    }
  1.3771 +    case NS_THEME_TAB_PANELS:
  1.3772 +      ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_SOFT | BF_MIDDLE |
  1.3773 +          BF_LEFT | BF_RIGHT | BF_BOTTOM);
  1.3774 +
  1.3775 +      break;
  1.3776 +    case NS_THEME_MENUBAR:
  1.3777 +      break;
  1.3778 +    case NS_THEME_MENUPOPUP:
  1.3779 +      NS_ASSERTION(nsUXThemeData::sFlatMenus, "Classic menus are styled entirely through CSS");
  1.3780 +      ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_MENU+1));
  1.3781 +      ::FrameRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_BTNSHADOW));
  1.3782 +      break;
  1.3783 +    case NS_THEME_MENUITEM:
  1.3784 +    case NS_THEME_CHECKMENUITEM:
  1.3785 +    case NS_THEME_RADIOMENUITEM:
  1.3786 +      // part == 0 for normal items
  1.3787 +      // part == 1 for top-level menu items
  1.3788 +      if (nsUXThemeData::sFlatMenus) {
  1.3789 +        // Not disabled and hot/pushed.
  1.3790 +        if ((state & (DFCS_HOT | DFCS_PUSHED)) != 0) {
  1.3791 +          ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_MENUHILIGHT+1));
  1.3792 +          ::FrameRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_HIGHLIGHT));
  1.3793 +        }
  1.3794 +      } else {
  1.3795 +        if (part == 1) {
  1.3796 +          if ((state & DFCS_INACTIVE) == 0) {
  1.3797 +            if ((state & DFCS_PUSHED) != 0) {
  1.3798 +              ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT);
  1.3799 +            } else if ((state & DFCS_HOT) != 0) {
  1.3800 +              ::DrawEdge(hdc, &widgetRect, BDR_RAISEDINNER, BF_RECT);
  1.3801 +            }
  1.3802 +          }
  1.3803 +        } else {
  1.3804 +          if ((state & (DFCS_HOT | DFCS_PUSHED)) != 0) {
  1.3805 +            ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
  1.3806 +          }
  1.3807 +        }
  1.3808 +      }
  1.3809 +      break;
  1.3810 +    case NS_THEME_MENUCHECKBOX:
  1.3811 +    case NS_THEME_MENURADIO:
  1.3812 +      if (!(state & DFCS_CHECKED))
  1.3813 +        break; // nothin' to do
  1.3814 +    case NS_THEME_MENUARROW: {
  1.3815 +      uint32_t color = COLOR_MENUTEXT;
  1.3816 +      if ((state & DFCS_INACTIVE))
  1.3817 +        color = COLOR_GRAYTEXT;
  1.3818 +      else if ((state & DFCS_HOT))
  1.3819 +        color = COLOR_HIGHLIGHTTEXT;
  1.3820 +      
  1.3821 +      if (aWidgetType == NS_THEME_MENUCHECKBOX)
  1.3822 +        DrawMenuImage(hdc, widgetRect, DFCS_MENUCHECK, color);
  1.3823 +      else if (aWidgetType == NS_THEME_MENURADIO)
  1.3824 +        DrawMenuImage(hdc, widgetRect, DFCS_MENUBULLET, color);
  1.3825 +      else if (aWidgetType == NS_THEME_MENUARROW)
  1.3826 +        DrawMenuImage(hdc, widgetRect, 
  1.3827 +                      (state & DFCS_RTL) ? DFCS_MENUARROWRIGHT : DFCS_MENUARROW,
  1.3828 +                      color);
  1.3829 +      break;
  1.3830 +    }
  1.3831 +    case NS_THEME_MENUSEPARATOR: {
  1.3832 +      // separators are offset by a bit (see menu.css)
  1.3833 +      widgetRect.left++;
  1.3834 +      widgetRect.right--;
  1.3835 +
  1.3836 +      // This magic number is brought to you by the value in menu.css
  1.3837 +      widgetRect.top += 4;
  1.3838 +      // Our rectangles are 1 pixel high (see border size in menu.css)
  1.3839 +      widgetRect.bottom = widgetRect.top+1;
  1.3840 +      ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_3DSHADOW+1));
  1.3841 +      widgetRect.top++;
  1.3842 +      widgetRect.bottom++;
  1.3843 +      ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_3DHILIGHT+1));
  1.3844 +      break;
  1.3845 +    }
  1.3846 +
  1.3847 +    case NS_THEME_WINDOW_TITLEBAR:
  1.3848 +    case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
  1.3849 +    {
  1.3850 +      RECT rect = widgetRect;
  1.3851 +      int32_t offset = GetSystemMetrics(SM_CXFRAME);
  1.3852 +      rect.bottom -= 1;
  1.3853 +
  1.3854 +      // first fill the area to the color of the window background
  1.3855 +      FillRect(hdc, &rect, (HBRUSH)(COLOR_3DFACE+1));
  1.3856 +
  1.3857 +      // inset the caption area so it doesn't overflow.
  1.3858 +      rect.top += offset;
  1.3859 +      // if enabled, draw a gradient titlebar background, otherwise
  1.3860 +      // fill with a solid color.
  1.3861 +      BOOL bFlag = TRUE;
  1.3862 +      SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bFlag, 0);
  1.3863 +      if (!bFlag) {
  1.3864 +        if (state == mozilla::widget::themeconst::FS_ACTIVE)
  1.3865 +          FillRect(hdc, &rect, (HBRUSH)(COLOR_ACTIVECAPTION+1));
  1.3866 +        else
  1.3867 +          FillRect(hdc, &rect, (HBRUSH)(COLOR_INACTIVECAPTION+1));
  1.3868 +      } else {
  1.3869 +        DWORD startColor, endColor;
  1.3870 +        if (state == mozilla::widget::themeconst::FS_ACTIVE) {
  1.3871 +          startColor = GetSysColor(COLOR_ACTIVECAPTION);
  1.3872 +          endColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
  1.3873 +        } else {
  1.3874 +          startColor = GetSysColor(COLOR_INACTIVECAPTION);
  1.3875 +          endColor = GetSysColor(COLOR_GRADIENTINACTIVECAPTION);
  1.3876 +        }
  1.3877 +
  1.3878 +        TRIVERTEX vertex[2];
  1.3879 +        vertex[0].x     = rect.left;
  1.3880 +        vertex[0].y     = rect.top;
  1.3881 +        vertex[0].Red   = GetRValue(startColor) << 8;
  1.3882 +        vertex[0].Green = GetGValue(startColor) << 8;
  1.3883 +        vertex[0].Blue  = GetBValue(startColor) << 8;
  1.3884 +        vertex[0].Alpha = 0;
  1.3885 +
  1.3886 +        vertex[1].x     = rect.right;
  1.3887 +        vertex[1].y     = rect.bottom; 
  1.3888 +        vertex[1].Red   = GetRValue(endColor) << 8;
  1.3889 +        vertex[1].Green = GetGValue(endColor) << 8;
  1.3890 +        vertex[1].Blue  = GetBValue(endColor) << 8;
  1.3891 +        vertex[1].Alpha = 0;
  1.3892 +
  1.3893 +        GRADIENT_RECT gRect;
  1.3894 +        gRect.UpperLeft  = 0;
  1.3895 +        gRect.LowerRight = 1;
  1.3896 +        // available on win2k & up
  1.3897 +        GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H);
  1.3898 +      }
  1.3899 +
  1.3900 +      if (aWidgetType == NS_THEME_WINDOW_TITLEBAR) {
  1.3901 +        // frame things up with a top raised border.
  1.3902 +        DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_TOP);
  1.3903 +      }
  1.3904 +      break;
  1.3905 +    }
  1.3906 +
  1.3907 +    case NS_THEME_WINDOW_FRAME_LEFT:
  1.3908 +      DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_LEFT);
  1.3909 +      break;
  1.3910 +
  1.3911 +    case NS_THEME_WINDOW_FRAME_RIGHT:
  1.3912 +      DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RIGHT);
  1.3913 +      break;
  1.3914 +
  1.3915 +    case NS_THEME_WINDOW_FRAME_BOTTOM:
  1.3916 +      DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_BOTTOM);
  1.3917 +      break;
  1.3918 +
  1.3919 +    case NS_THEME_WINDOW_BUTTON_CLOSE:
  1.3920 +    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
  1.3921 +    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
  1.3922 +    case NS_THEME_WINDOW_BUTTON_RESTORE:
  1.3923 +    {
  1.3924 +      if (aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE) {
  1.3925 +        OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_MINIMIZE);
  1.3926 +      }
  1.3927 +      else if (aWidgetType == NS_THEME_WINDOW_BUTTON_MAXIMIZE ||
  1.3928 +               aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
  1.3929 +        OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_RESTORE);
  1.3930 +      }
  1.3931 +      else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) {
  1.3932 +        OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_CLOSE);
  1.3933 +      }
  1.3934 +      int32_t oldTA = SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
  1.3935 +      DrawFrameControl(hdc, &widgetRect, part, state);
  1.3936 +      SetTextAlign(hdc, oldTA);
  1.3937 +      break;
  1.3938 +    }
  1.3939 +
  1.3940 +    default:
  1.3941 +      rv = NS_ERROR_FAILURE;
  1.3942 +      break;
  1.3943 +  }
  1.3944 +
  1.3945 +  nativeDrawing.EndNativeDrawing();
  1.3946 +
  1.3947 +  if (NS_FAILED(rv))
  1.3948 +    return rv;
  1.3949 +
  1.3950 +  if (nativeDrawing.ShouldRenderAgain())
  1.3951 +    goto RENDER_AGAIN;
  1.3952 +
  1.3953 +  nativeDrawing.PaintToContext();
  1.3954 +
  1.3955 +  return rv;
  1.3956 +}
  1.3957 +
  1.3958 +uint32_t
  1.3959 +nsNativeThemeWin::GetWidgetNativeDrawingFlags(uint8_t aWidgetType)
  1.3960 +{
  1.3961 +  switch (aWidgetType) {
  1.3962 +    case NS_THEME_BUTTON:
  1.3963 +    case NS_THEME_NUMBER_INPUT:
  1.3964 +    case NS_THEME_TEXTFIELD:
  1.3965 +    case NS_THEME_TEXTFIELD_MULTILINE:
  1.3966 +
  1.3967 +    case NS_THEME_DROPDOWN:
  1.3968 +    case NS_THEME_DROPDOWN_TEXTFIELD:
  1.3969 +      return
  1.3970 +        gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
  1.3971 +        gfxWindowsNativeDrawing::CAN_AXIS_ALIGNED_SCALE |
  1.3972 +        gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
  1.3973 +
  1.3974 +    // need to check these others
  1.3975 +    case NS_THEME_RANGE:
  1.3976 +    case NS_THEME_RANGE_THUMB:
  1.3977 +    case NS_THEME_SCROLLBAR_BUTTON_UP:
  1.3978 +    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
  1.3979 +    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
  1.3980 +    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
  1.3981 +    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
  1.3982 +    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
  1.3983 +    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
  1.3984 +    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
  1.3985 +    case NS_THEME_SCALE_HORIZONTAL:
  1.3986 +    case NS_THEME_SCALE_VERTICAL:
  1.3987 +    case NS_THEME_SCALE_THUMB_HORIZONTAL:
  1.3988 +    case NS_THEME_SCALE_THUMB_VERTICAL:
  1.3989 +    case NS_THEME_SPINNER_UP_BUTTON:
  1.3990 +    case NS_THEME_SPINNER_DOWN_BUTTON:
  1.3991 +    case NS_THEME_LISTBOX:
  1.3992 +    case NS_THEME_TREEVIEW:
  1.3993 +    case NS_THEME_TOOLTIP:
  1.3994 +    case NS_THEME_STATUSBAR:
  1.3995 +    case NS_THEME_STATUSBAR_PANEL:
  1.3996 +    case NS_THEME_STATUSBAR_RESIZER_PANEL:
  1.3997 +    case NS_THEME_RESIZER:
  1.3998 +    case NS_THEME_PROGRESSBAR:
  1.3999 +    case NS_THEME_PROGRESSBAR_VERTICAL:
  1.4000 +    case NS_THEME_PROGRESSBAR_CHUNK:
  1.4001 +    case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
  1.4002 +    case NS_THEME_TAB:
  1.4003 +    case NS_THEME_TAB_PANEL:
  1.4004 +    case NS_THEME_TAB_PANELS:
  1.4005 +    case NS_THEME_MENUBAR:
  1.4006 +    case NS_THEME_MENUPOPUP:
  1.4007 +    case NS_THEME_MENUITEM:
  1.4008 +      break;
  1.4009 +
  1.4010 +    // the dropdown button /almost/ renders correctly with scaling,
  1.4011 +    // except that the graphic in the dropdown button (the downward arrow)
  1.4012 +    // doesn't get scaled up.
  1.4013 +    case NS_THEME_DROPDOWN_BUTTON:
  1.4014 +    // these are definitely no; they're all graphics that don't get scaled up
  1.4015 +    case NS_THEME_CHECKBOX:
  1.4016 +    case NS_THEME_RADIO:
  1.4017 +    case NS_THEME_GROUPBOX:
  1.4018 +    case NS_THEME_CHECKMENUITEM:
  1.4019 +    case NS_THEME_RADIOMENUITEM:
  1.4020 +    case NS_THEME_MENUCHECKBOX:
  1.4021 +    case NS_THEME_MENURADIO:
  1.4022 +    case NS_THEME_MENUARROW:
  1.4023 +      return
  1.4024 +        gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
  1.4025 +        gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE |
  1.4026 +        gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
  1.4027 +  }
  1.4028 +
  1.4029 +  return
  1.4030 +    gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
  1.4031 +    gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE |
  1.4032 +    gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
  1.4033 +}
  1.4034 +
  1.4035 +///////////////////////////////////////////
  1.4036 +// Creation Routine
  1.4037 +///////////////////////////////////////////
  1.4038 +
  1.4039 +// from nsWindow.cpp
  1.4040 +extern bool gDisableNativeTheme;
  1.4041 +
  1.4042 +nsresult NS_NewNativeTheme(nsISupports *aOuter, REFNSIID aIID, void **aResult)
  1.4043 +{
  1.4044 +  if (gDisableNativeTheme)
  1.4045 +    return NS_ERROR_NO_INTERFACE;
  1.4046 +
  1.4047 +  if (aOuter)
  1.4048 +    return NS_ERROR_NO_AGGREGATION;
  1.4049 +
  1.4050 +  nsNativeThemeWin* theme = new nsNativeThemeWin();
  1.4051 +  if (!theme)
  1.4052 +    return NS_ERROR_OUT_OF_MEMORY;
  1.4053 +  return theme->QueryInterface(aIID, aResult);
  1.4054 +}

mercurial