1 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsNativeThemeWin.h"
8 #include "nsRenderingContext.h"
11 #include "nsTransform2D.h"
12 #include "nsThemeConstants.h"
13 #include "nsIPresShell.h"
14 #include "nsPresContext.h"
15 #include "nsIContent.h"
17 #include "nsEventStates.h"
18 #include "nsINameSpaceManager.h"
19 #include "nsIDOMHTMLInputElement.h"
20 #include "nsMenuFrame.h"
21 #include "nsGkAtoms.h"
24 #include "nsIComboboxControlFrame.h"
28 #include "gfxPlatform.h"
29 #include "gfxContext.h"
30 #include "gfxMatrix.h"
31 #include "gfxWindowsPlatform.h"
32 #include "gfxWindowsSurface.h"
33 #include "gfxWindowsNativeDrawing.h"
35 #include "nsUXThemeData.h"
36 #include "nsUXThemeConstants.h"
39 using namespace mozilla::widget
;
42 extern PRLogModuleInfo
* gWindowsLog
;
45 NS_IMPL_ISUPPORTS_INHERITED1(nsNativeThemeWin
, nsNativeTheme
, nsITheme
)
47 nsNativeThemeWin::nsNativeThemeWin() :
48 mProgressDeterminateTimeStamp(TimeStamp::Now()),
49 mProgressIndeterminateTimeStamp(TimeStamp::Now())
51 // If there is a relevant change in forms.css for windows platform,
52 // static widget style variables (e.g. sButtonBorderSize) should be
53 // reinitialized here.
56 nsNativeThemeWin::~nsNativeThemeWin()
58 nsUXThemeData::Invalidate();
62 GetTopLevelWindowActiveState(nsIFrame
*aFrame
)
64 // Get the widget. nsIFrame's GetNearestWidget walks up the view chain
65 // until it finds a real window.
66 nsIWidget
* widget
= aFrame
->GetNearestWidget();
67 nsWindowBase
* window
= static_cast<nsWindowBase
*>(widget
);
69 return mozilla::widget::themeconst::FS_INACTIVE
;
70 if (widget
&& !window
->IsTopLevelWidget() &&
71 !(window
= window
->GetParentWindowBase(false)))
72 return mozilla::widget::themeconst::FS_INACTIVE
;
74 if (window
->GetWindowHandle() == ::GetActiveWindow())
75 return mozilla::widget::themeconst::FS_ACTIVE
;
76 return mozilla::widget::themeconst::FS_INACTIVE
;
80 GetWindowFrameButtonState(nsIFrame
*aFrame
, nsEventStates eventState
)
82 if (GetTopLevelWindowActiveState(aFrame
) ==
83 mozilla::widget::themeconst::FS_INACTIVE
) {
84 if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
85 return mozilla::widget::themeconst::BS_HOT
;
86 return mozilla::widget::themeconst::BS_INACTIVE
;
89 if (eventState
.HasState(NS_EVENT_STATE_HOVER
)) {
90 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
))
91 return mozilla::widget::themeconst::BS_PUSHED
;
92 return mozilla::widget::themeconst::BS_HOT
;
94 return mozilla::widget::themeconst::BS_NORMAL
;
98 GetClassicWindowFrameButtonState(nsEventStates eventState
)
100 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
) &&
101 eventState
.HasState(NS_EVENT_STATE_HOVER
))
102 return DFCS_BUTTONPUSH
|DFCS_PUSHED
;
103 return DFCS_BUTTONPUSH
;
107 IsTopLevelMenu(nsIFrame
*aFrame
)
109 bool isTopLevel(false);
110 nsMenuFrame
*menuFrame
= do_QueryFrame(aFrame
);
112 isTopLevel
= menuFrame
->IsOnMenuBar();
118 GetCheckboxMargins(HANDLE theme
, HDC hdc
)
120 MARGINS checkboxContent
= {0};
121 GetThemeMargins(theme
, hdc
, MENU_POPUPCHECK
, MCB_NORMAL
,
122 TMT_CONTENTMARGINS
, nullptr, &checkboxContent
);
123 return checkboxContent
;
127 GetCheckboxBGSize(HANDLE theme
, HDC hdc
)
130 GetThemePartSize(theme
, hdc
, MENU_POPUPCHECK
, MC_CHECKMARKNORMAL
,
131 nullptr, TS_TRUE
, &checkboxSize
);
133 MARGINS checkboxMargins
= GetCheckboxMargins(theme
, hdc
);
135 int leftMargin
= checkboxMargins
.cxLeftWidth
;
136 int rightMargin
= checkboxMargins
.cxRightWidth
;
137 int topMargin
= checkboxMargins
.cyTopHeight
;
138 int bottomMargin
= checkboxMargins
.cyBottomHeight
;
140 int width
= leftMargin
+ checkboxSize
.cx
+ rightMargin
;
141 int height
= topMargin
+ checkboxSize
.cy
+ bottomMargin
;
149 GetCheckboxBGBounds(HANDLE theme
, HDC hdc
)
151 MARGINS checkboxBGSizing
= {0};
152 MARGINS checkboxBGContent
= {0};
153 GetThemeMargins(theme
, hdc
, MENU_POPUPCHECKBACKGROUND
, MCB_NORMAL
,
154 TMT_SIZINGMARGINS
, nullptr, &checkboxBGSizing
);
155 GetThemeMargins(theme
, hdc
, MENU_POPUPCHECKBACKGROUND
, MCB_NORMAL
,
156 TMT_CONTENTMARGINS
, nullptr, &checkboxBGContent
);
158 #define posdx(d) ((d) > 0 ? d : 0)
160 int dx
= posdx(checkboxBGContent
.cxRightWidth
-
161 checkboxBGSizing
.cxRightWidth
) +
162 posdx(checkboxBGContent
.cxLeftWidth
-
163 checkboxBGSizing
.cxLeftWidth
);
164 int dy
= posdx(checkboxBGContent
.cyTopHeight
-
165 checkboxBGSizing
.cyTopHeight
) +
166 posdx(checkboxBGContent
.cyBottomHeight
-
167 checkboxBGSizing
.cyBottomHeight
);
171 SIZE
ret(GetCheckboxBGSize(theme
, hdc
));
178 GetGutterSize(HANDLE theme
, HDC hdc
)
181 GetThemePartSize(theme
, hdc
, MENU_POPUPGUTTER
, 0, nullptr, TS_TRUE
, &gutterSize
);
183 SIZE
checkboxBGSize(GetCheckboxBGBounds(theme
, hdc
));
186 GetThemePartSize(theme
, hdc
, MENU_POPUPITEM
, MPI_NORMAL
, nullptr, TS_TRUE
, &itemSize
);
188 // Figure out how big the menuitem's icon will be (if present) at current DPI
189 double scaleFactor
= nsIWidget::DefaultScaleOverride();
190 if (scaleFactor
<= 0.0) {
191 scaleFactor
= gfxWindowsPlatform::GetPlatform()->GetDPIScale();
193 int iconDevicePixels
= NSToIntRound(16 * scaleFactor
);
195 iconDevicePixels
, iconDevicePixels
197 // Not really sure what margins should be used here, but this seems to work in practice...
198 MARGINS margins
= {0};
199 GetThemeMargins(theme
, hdc
, MENU_POPUPCHECKBACKGROUND
, MCB_NORMAL
,
200 TMT_CONTENTMARGINS
, nullptr, &margins
);
201 iconSize
.cx
+= margins
.cxLeftWidth
+ margins
.cxRightWidth
;
202 iconSize
.cy
+= margins
.cyTopHeight
+ margins
.cyBottomHeight
;
204 int width
= std::max(itemSize
.cx
, std::max(iconSize
.cx
, checkboxBGSize
.cx
) + gutterSize
.cx
);
205 int height
= std::max(itemSize
.cy
, std::max(iconSize
.cy
, checkboxBGSize
.cy
));
213 /* DrawThemeBGRTLAware - render a theme part based on rtl state.
214 * Some widgets are not direction-neutral and need to be drawn reversed for
215 * RTL. Windows provides a way to do this with SetLayout, but this reverses
216 * the entire drawing area of a given device context, which means that its
217 * use will also affect the positioning of the widget. There are two ways
218 * to work around this:
220 * Option 1: Alter the position of the rect that we send so that we cancel
221 * out the positioning effects of SetLayout
222 * Option 2: Create a memory DC with the widgetRect's dimensions, draw onto
223 * that, and then transfer the results back to our DC
225 * This function tries to implement option 1, under the assumption that the
226 * correct way to reverse the effects of SetLayout is to translate the rect
227 * such that the offset from the DC bitmap's left edge to the old rect's
228 * left edge is equal to the offset from the DC bitmap's right edge to the
229 * new rect's right edge. In other words,
230 * (oldRect.left + vpOrg.x) == ((dcBMP.width - vpOrg.x) - newRect.right)
233 DrawThemeBGRTLAware(HANDLE aTheme
, HDC aHdc
, int aPart
, int aState
,
234 const RECT
*aWidgetRect
, const RECT
*aClipRect
,
237 NS_ASSERTION(aTheme
, "Bad theme handle.");
238 NS_ASSERTION(aHdc
, "Bad hdc.");
239 NS_ASSERTION(aWidgetRect
, "Bad rect.");
240 NS_ASSERTION(aClipRect
, "Bad clip rect.");
243 return DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
,
244 aWidgetRect
, aClipRect
);
247 HGDIOBJ hObj
= GetCurrentObject(aHdc
, OBJ_BITMAP
);
251 if (hObj
&& GetObject(hObj
, sizeof(bitmap
), &bitmap
) &&
252 GetViewportOrgEx(aHdc
, &vpOrg
)) {
253 RECT
newWRect(*aWidgetRect
);
254 newWRect
.left
= bitmap
.bmWidth
- (aWidgetRect
->right
+ 2*vpOrg
.x
);
255 newWRect
.right
= bitmap
.bmWidth
- (aWidgetRect
->left
+ 2*vpOrg
.x
);
258 RECT
*newCRectPtr
= nullptr;
261 newCRect
.top
= aClipRect
->top
;
262 newCRect
.bottom
= aClipRect
->bottom
;
263 newCRect
.left
= bitmap
.bmWidth
- (aClipRect
->right
+ 2*vpOrg
.x
);
264 newCRect
.right
= bitmap
.bmWidth
- (aClipRect
->left
+ 2*vpOrg
.x
);
265 newCRectPtr
= &newCRect
;
268 SetLayout(aHdc
, LAYOUT_RTL
);
269 HRESULT hr
= DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
, &newWRect
,
276 return DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
,
277 aWidgetRect
, aClipRect
);
281 * Caption button padding data - 'hot' button padding.
282 * These areas are considered hot, in that they activate
283 * a button when hovered or clicked. The button graphic
284 * is drawn inside the padding border. Unrecognized themes
285 * are treated as their recognized counterparts for now.
286 * left top right bottom
287 * classic min 1 2 0 1
288 * classic max 0 2 1 1
289 * classic close 1 2 2 1
291 * aero basic min 1 2 0 2
292 * aero basic max 0 2 1 2
293 * aero basic close 1 2 1 2
295 * xp theme min 0 2 0 2
296 * xp theme max 0 2 1 2
297 * xp theme close 1 2 2 2
299 * 'cold' button padding - generic button padding, should
301 * left top right bottom
302 * classic min 0 0 0 0
303 * classic max 0 0 0 0
304 * classic close 0 0 0 0
306 * aero basic min 0 0 1 0
307 * aero basic max 1 0 0 0
308 * aero basic close 0 0 0 0
310 * xp theme min 0 0 1 0
311 * xp theme max 1 0 0 0
312 * xp theme close 0 0 0 0
315 enum CaptionDesktopTheme
{
322 CAPTIONBUTTON_MINIMIZE
= 0,
323 CAPTIONBUTTON_RESTORE
,
327 struct CaptionButtonPadding
{
331 // RECT: left, top, right, bottom
332 static CaptionButtonPadding buttonData
[3] = {
334 { { 1, 2, 0, 1 }, { 0, 2, 1, 1 }, { 1, 2, 2, 1 } }
337 { { 1, 2, 0, 2 }, { 0, 2, 1, 2 }, { 1, 2, 2, 2 } }
340 { { 0, 2, 0, 2 }, { 0, 2, 1, 2 }, { 1, 2, 2, 2 } }
344 // Adds "hot" caption button padding to minimum widget size.
346 AddPaddingRect(nsIntSize
* aSize
, CaptionButton button
) {
351 offset
= buttonData
[CAPTION_CLASSIC
].hotPadding
[button
];
352 else if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
)
353 offset
= buttonData
[CAPTION_XPTHEME
].hotPadding
[button
];
355 offset
= buttonData
[CAPTION_BASIC
].hotPadding
[button
];
356 aSize
->width
+= offset
.left
+ offset
.right
;
357 aSize
->height
+= offset
.top
+ offset
.bottom
;
360 // If we've added padding to the minimum widget size, offset
361 // the area we draw into to compensate.
363 OffsetBackgroundRect(RECT
& rect
, CaptionButton button
) {
366 offset
= buttonData
[CAPTION_CLASSIC
].hotPadding
[button
];
367 else if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
)
368 offset
= buttonData
[CAPTION_XPTHEME
].hotPadding
[button
];
370 offset
= buttonData
[CAPTION_BASIC
].hotPadding
[button
];
371 rect
.left
+= offset
.left
;
372 rect
.top
+= offset
.top
;
373 rect
.right
-= offset
.right
;
374 rect
.bottom
-= offset
.bottom
;
378 * Notes on progress track and meter part constants:
380 * PP_BAR(_VERT) - base progress track
381 * PP_TRANSPARENTBAR(_VERT) - transparent progress track. this only works if
382 * the underlying surface supports alpha. otherwise
383 * theme lib's DrawThemeBackground falls back on
384 * opaque PP_BAR. we currently don't use this.
385 * PP_CHUNK(_VERT) - xp progress meter. this does not draw an xp style
386 * progress w/chunks, it draws fill using the chunk
389 * PP_FILL(_VERT) - progress meter. these have four states/colors.
390 * PP_PULSEOVERLAY(_VERT) - white reflection - an overlay, not sure what this
392 * PP_MOVEOVERLAY(_VERT) - green pulse - the pulse effect overlay on
393 * determined progress bars. we also use this for
394 * indeterminate chunk.
396 * Notes on state constants:
397 * PBBS_NORMAL - green progress
398 * PBBVS_PARTIAL/PBFVS_ERROR - red error progress
399 * PBFS_PAUSED - yellow paused progress
401 * There is no common controls style indeterminate part on vista and up.
405 * Progress bar related constants. These values are found by experimenting and
406 * comparing against native widgets used by the system. They are very unlikely
407 * exact but try to not be too wrong.
409 // The amount of time we animate progress meters parts across the frame.
410 static const double kProgressDeterminateTimeSpan
= 3.0;
411 static const double kProgressIndeterminateTimeSpan
= 5.0;
412 // The width of the overlay used to animate the horizontal progress bar (Vista and later).
413 static const int32_t kProgressHorizontalVistaOverlaySize
= 120;
414 // The width of the overlay used for the horizontal indeterminate progress bars on XP.
415 static const int32_t kProgressHorizontalXPOverlaySize
= 55;
416 // The height of the overlay used to animate the vertical progress bar (Vista and later).
417 static const int32_t kProgressVerticalOverlaySize
= 45;
418 // The height of the overlay used for the vertical indeterminate progress bar (Vista and later).
419 static const int32_t kProgressVerticalIndeterminateOverlaySize
= 60;
420 // The width of the overlay used to animate the indeterminate progress bar (Windows Classic).
421 static const int32_t kProgressClassicOverlaySize
= 40;
424 * GetProgressOverlayStyle - returns the proper overlay part for themed
425 * progress bars based on os and orientation.
428 GetProgressOverlayStyle(bool aIsVertical
)
431 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
432 return PP_MOVEOVERLAYVERT
;
436 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
437 return PP_MOVEOVERLAY
;
444 * GetProgressOverlaySize - returns the minimum width or height for themed
445 * progress bar overlays. This includes the width of indeterminate chunks
446 * and vista pulse overlays.
449 GetProgressOverlaySize(bool aIsVertical
, bool aIsIndeterminate
)
451 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
453 return aIsIndeterminate
? kProgressVerticalIndeterminateOverlaySize
454 : kProgressVerticalOverlaySize
;
456 return kProgressHorizontalVistaOverlaySize
;
458 return kProgressHorizontalXPOverlaySize
;
462 * IsProgressMeterFilled - Determines if a progress meter is at 100% fill based
463 * on a comparison of the current value and maximum.
466 IsProgressMeterFilled(nsIFrame
* aFrame
)
468 NS_ENSURE_TRUE(aFrame
, false);
469 nsIFrame
* parentFrame
= aFrame
->GetParent();
470 NS_ENSURE_TRUE(parentFrame
, false);
471 return nsNativeTheme::GetProgressValue(parentFrame
) ==
472 nsNativeTheme::GetProgressMaxValue(parentFrame
);
476 * CalculateProgressOverlayRect - returns the padded overlay animation rect
477 * used in rendering progress bars. Resulting rects are used in rendering
478 * vista+ pulse overlays and indeterminate progress meters. Graphics should
479 * be rendered at the origin.
482 nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame
* aFrame
,
485 bool aIsIndeterminate
,
488 NS_ASSERTION(aFrame
, "bad frame pointer");
489 NS_ASSERTION(aWidgetRect
, "bad rect pointer");
491 int32_t frameSize
= aIsVertical
? aWidgetRect
->bottom
- aWidgetRect
->top
492 : aWidgetRect
->right
- aWidgetRect
->left
;
494 // Recycle a set of progress pulse timers - these timers control the position
495 // of all progress overlays and indeterminate chunks that get rendered.
496 double span
= aIsIndeterminate
? kProgressIndeterminateTimeSpan
497 : kProgressDeterminateTimeSpan
;
499 if (!aIsIndeterminate
) {
500 if (TimeStamp::Now() > (mProgressDeterminateTimeStamp
+
501 TimeDuration::FromSeconds(span
))) {
502 mProgressDeterminateTimeStamp
= TimeStamp::Now();
504 period
= TimeStamp::Now() - mProgressDeterminateTimeStamp
;
506 if (TimeStamp::Now() > (mProgressIndeterminateTimeStamp
+
507 TimeDuration::FromSeconds(span
))) {
508 mProgressIndeterminateTimeStamp
= TimeStamp::Now();
510 period
= TimeStamp::Now() - mProgressIndeterminateTimeStamp
;
513 double percent
= period
/ TimeDuration::FromSeconds(span
);
515 if (!aIsVertical
&& IsFrameRTL(aFrame
))
516 percent
= 1 - percent
;
518 RECT overlayRect
= *aWidgetRect
;
521 overlaySize
= GetProgressOverlaySize(aIsVertical
, aIsIndeterminate
);
523 overlaySize
= kProgressClassicOverlaySize
;
526 // Calculate a bounds that is larger than the meters frame such that the
527 // overlay starts and ends completely off the edge of the frame:
528 // [overlay][frame][overlay]
529 // This also yields a nice delay on rotation. Use overlaySize as the minimum
530 // size for [overlay] based on the graphics dims. If [frame] is larger, use
531 // the frame size instead.
532 int trackWidth
= frameSize
> overlaySize
? frameSize
: overlaySize
;
534 int xPos
= aWidgetRect
->left
- trackWidth
;
535 xPos
+= (int)ceil(((double)(trackWidth
*2) * percent
));
536 overlayRect
.left
= xPos
;
537 overlayRect
.right
= xPos
+ overlaySize
;
539 int yPos
= aWidgetRect
->bottom
+ trackWidth
;
540 yPos
-= (int)ceil(((double)(trackWidth
*2) * percent
));
541 overlayRect
.bottom
= yPos
;
542 overlayRect
.top
= yPos
- overlaySize
;
548 * DrawChunkProgressMeter - renders an xp style chunked progress meter. Called
549 * by DrawProgressMeter.
551 * @param aTheme progress theme handle
552 * @param aHdc hdc returned by gfxWindowsNativeDrawing
553 * @param aPart the PP_X progress part
554 * @param aState the theme state
555 * @param aFrame the elements frame
556 * @param aWidgetRect bounding rect for the widget
557 * @param aClipRect dirty rect that needs drawing.
558 * @param aAppUnits app units per device pixel
559 * @param aIsIndeterm is an indeterminate progress?
560 * @param aIsVertical render a vertical progress?
561 * @param aIsRtl direction is rtl
564 DrawChunkProgressMeter(HTHEME aTheme
, HDC aHdc
, int aPart
,
565 int aState
, nsIFrame
* aFrame
, RECT
* aWidgetRect
,
566 RECT
* aClipRect
, gfxFloat aAppUnits
, bool aIsIndeterm
,
567 bool aIsVertical
, bool aIsRtl
)
569 NS_ASSERTION(aTheme
, "Bad theme.");
570 NS_ASSERTION(aHdc
, "Bad hdc.");
571 NS_ASSERTION(aWidgetRect
, "Bad rect.");
572 NS_ASSERTION(aClipRect
, "Bad clip rect.");
573 NS_ASSERTION(aFrame
, "Bad frame.");
575 // For horizontal meters, the theme lib paints the right graphic but doesn't
576 // paint the chunks, so we do that manually. For vertical meters, the theme
577 // library draws everything correctly.
579 DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
, aWidgetRect
, aClipRect
);
583 // query for the proper chunk metrics
584 int chunkSize
, spaceSize
;
585 if (FAILED(GetThemeMetric(aTheme
, aHdc
, aPart
, aState
,
586 TMT_PROGRESSCHUNKSIZE
, &chunkSize
)) ||
587 FAILED(GetThemeMetric(aTheme
, aHdc
, aPart
, aState
,
588 TMT_PROGRESSSPACESIZE
, &spaceSize
))) {
589 DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
, aWidgetRect
, aClipRect
);
594 if (!aIsRtl
|| aIsIndeterm
) {
595 for (int chunk
= aWidgetRect
->left
; chunk
<= aWidgetRect
->right
;
596 chunk
+= (chunkSize
+spaceSize
)) {
597 if (!aIsIndeterm
&& ((chunk
+ chunkSize
) > aWidgetRect
->right
)) {
598 // aWidgetRect->right represents the end of the meter. Partial blocks
599 // don't get rendered with one exception, so exit here if we don't have
600 // a full chunk to draw.
601 // The above is true *except* when the meter is at 100% fill, in which
602 // case Windows renders any remaining partial block. Query the parent
603 // frame to find out if we're at 100%.
604 if (!IsProgressMeterFilled(aFrame
)) {
609 { chunk
, aWidgetRect
->top
, chunk
+ chunkSize
, aWidgetRect
->bottom
};
610 DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
, &bounds
, aClipRect
);
613 // rtl needs to grow in the opposite direction to look right.
614 for (int chunk
= aWidgetRect
->right
; chunk
>= aWidgetRect
->left
;
615 chunk
-= (chunkSize
+spaceSize
)) {
616 if ((chunk
- chunkSize
) < aWidgetRect
->left
) {
617 if (!IsProgressMeterFilled(aFrame
)) {
622 { chunk
- chunkSize
, aWidgetRect
->top
, chunk
, aWidgetRect
->bottom
};
623 DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
, &bounds
, aClipRect
);
629 * DrawProgressMeter - render an appropriate progress meter based on progress
630 * meter style, orientation, and os. Note, this does not render the underlying
633 * @param aFrame the widget frame
634 * @param aWidgetType type of widget
635 * @param aTheme progress theme handle
636 * @param aHdc hdc returned by gfxWindowsNativeDrawing
637 * @param aPart the PP_X progress part
638 * @param aState the theme state
639 * @param aWidgetRect bounding rect for the widget
640 * @param aClipRect dirty rect that needs drawing.
641 * @param aAppUnits app units per device pixel
644 nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame
* aFrame
, int aWidgetType
,
645 HANDLE aTheme
, HDC aHdc
,
646 int aPart
, int aState
,
647 RECT
* aWidgetRect
, RECT
* aClipRect
,
650 if (!aFrame
|| !aTheme
|| !aHdc
)
653 NS_ASSERTION(aWidgetRect
, "bad rect pointer");
654 NS_ASSERTION(aClipRect
, "bad clip rect pointer");
656 RECT adjWidgetRect
, adjClipRect
;
657 adjWidgetRect
= *aWidgetRect
;
658 adjClipRect
= *aClipRect
;
659 if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
) {
660 // Adjust clipping out by one pixel. XP progress meters are inset,
662 InflateRect(&adjWidgetRect
, 1, 1);
663 InflateRect(&adjClipRect
, 1, 1);
666 nsIFrame
* parentFrame
= aFrame
->GetParent();
668 // We have no parent to work with, just bail.
669 NS_WARNING("No parent frame for progress rendering. Can't paint.");
673 nsEventStates eventStates
= GetContentState(parentFrame
, aWidgetType
);
674 bool vertical
= IsVerticalProgress(parentFrame
) ||
675 aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
;
676 bool indeterminate
= IsIndeterminateProgress(parentFrame
, eventStates
);
677 bool animate
= indeterminate
;
679 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
680 // Vista and up progress meter is fill style, rendered here. We render
681 // the pulse overlay in the follow up section below.
682 DrawThemeBackground(aTheme
, aHdc
, aPart
, aState
,
683 &adjWidgetRect
, &adjClipRect
);
684 if (!IsProgressMeterFilled(aFrame
)) {
687 } else if (!indeterminate
) {
688 // XP progress meters are 'chunk' style.
689 DrawChunkProgressMeter(aTheme
, aHdc
, aPart
, aState
, aFrame
,
690 &adjWidgetRect
, &adjClipRect
, aAppUnits
,
691 indeterminate
, vertical
, IsFrameRTL(aFrame
));
695 // Indeterminate rendering
696 int32_t overlayPart
= GetProgressOverlayStyle(vertical
);
698 CalculateProgressOverlayRect(aFrame
, &adjWidgetRect
, vertical
,
699 indeterminate
, false);
700 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
701 DrawThemeBackground(aTheme
, aHdc
, overlayPart
, aState
, &overlayRect
,
704 DrawChunkProgressMeter(aTheme
, aHdc
, overlayPart
, aState
, aFrame
,
705 &overlayRect
, &adjClipRect
, aAppUnits
,
706 indeterminate
, vertical
, IsFrameRTL(aFrame
));
709 if (!QueueAnimatedContentForRefresh(aFrame
->GetContent(), 60)) {
710 NS_WARNING("unable to animate progress widget!");
716 nsNativeThemeWin::GetTheme(uint8_t aWidgetType
)
718 if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
) {
719 // On XP or earlier, render dropdowns as textfields;
720 // doing it the right way works fine with the MS themes,
721 // but breaks on a lot of custom themes (presumably because MS
722 // apps do the textfield border business as well).
723 if (aWidgetType
== NS_THEME_DROPDOWN
)
724 aWidgetType
= NS_THEME_TEXTFIELD
;
727 switch (aWidgetType
) {
728 case NS_THEME_BUTTON
:
730 case NS_THEME_CHECKBOX
:
731 case NS_THEME_GROUPBOX
:
732 return nsUXThemeData::GetTheme(eUXButton
);
733 case NS_THEME_TEXTFIELD
:
734 case NS_THEME_TEXTFIELD_MULTILINE
:
735 return nsUXThemeData::GetTheme(eUXEdit
);
736 case NS_THEME_TOOLTIP
:
737 // XP/2K3 should force a classic treatment of tooltips
738 return WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
?
739 nullptr : nsUXThemeData::GetTheme(eUXTooltip
);
740 case NS_THEME_TOOLBOX
:
741 return nsUXThemeData::GetTheme(eUXRebar
);
742 case NS_THEME_WIN_MEDIA_TOOLBOX
:
743 return nsUXThemeData::GetTheme(eUXMediaRebar
);
744 case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX
:
745 return nsUXThemeData::GetTheme(eUXCommunicationsRebar
);
746 case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX
:
747 return nsUXThemeData::GetTheme(eUXBrowserTabBarRebar
);
748 case NS_THEME_TOOLBAR
:
749 case NS_THEME_TOOLBAR_BUTTON
:
750 case NS_THEME_TOOLBAR_SEPARATOR
:
751 return nsUXThemeData::GetTheme(eUXToolbar
);
752 case NS_THEME_PROGRESSBAR
:
753 case NS_THEME_PROGRESSBAR_VERTICAL
:
754 case NS_THEME_PROGRESSBAR_CHUNK
:
755 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
756 return nsUXThemeData::GetTheme(eUXProgress
);
758 case NS_THEME_TAB_PANEL
:
759 case NS_THEME_TAB_PANELS
:
760 return nsUXThemeData::GetTheme(eUXTab
);
761 case NS_THEME_SCROLLBAR
:
762 case NS_THEME_SCROLLBAR_SMALL
:
763 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
764 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
765 case NS_THEME_SCROLLBAR_BUTTON_UP
:
766 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
767 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
768 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
769 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
770 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
771 return nsUXThemeData::GetTheme(eUXScrollbar
);
773 case NS_THEME_RANGE_THUMB
:
774 case NS_THEME_SCALE_HORIZONTAL
:
775 case NS_THEME_SCALE_VERTICAL
:
776 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
777 case NS_THEME_SCALE_THUMB_VERTICAL
:
778 return nsUXThemeData::GetTheme(eUXTrackbar
);
779 case NS_THEME_SPINNER_UP_BUTTON
:
780 case NS_THEME_SPINNER_DOWN_BUTTON
:
781 return nsUXThemeData::GetTheme(eUXSpin
);
782 case NS_THEME_STATUSBAR
:
783 case NS_THEME_STATUSBAR_PANEL
:
784 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
785 case NS_THEME_RESIZER
:
786 return nsUXThemeData::GetTheme(eUXStatus
);
787 case NS_THEME_DROPDOWN
:
788 case NS_THEME_DROPDOWN_BUTTON
:
789 return nsUXThemeData::GetTheme(eUXCombobox
);
790 case NS_THEME_TREEVIEW_HEADER_CELL
:
791 case NS_THEME_TREEVIEW_HEADER_SORTARROW
:
792 return nsUXThemeData::GetTheme(eUXHeader
);
793 case NS_THEME_LISTBOX
:
794 case NS_THEME_LISTBOX_LISTITEM
:
795 case NS_THEME_TREEVIEW
:
796 case NS_THEME_TREEVIEW_TWISTY_OPEN
:
797 case NS_THEME_TREEVIEW_TREEITEM
:
798 return nsUXThemeData::GetTheme(eUXListview
);
799 case NS_THEME_MENUBAR
:
800 case NS_THEME_MENUPOPUP
:
801 case NS_THEME_MENUITEM
:
802 case NS_THEME_CHECKMENUITEM
:
803 case NS_THEME_RADIOMENUITEM
:
804 case NS_THEME_MENUCHECKBOX
:
805 case NS_THEME_MENURADIO
:
806 case NS_THEME_MENUSEPARATOR
:
807 case NS_THEME_MENUARROW
:
808 case NS_THEME_MENUIMAGE
:
809 case NS_THEME_MENUITEMTEXT
:
810 return nsUXThemeData::GetTheme(eUXMenu
);
811 case NS_THEME_WINDOW_TITLEBAR
:
812 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
813 case NS_THEME_WINDOW_FRAME_LEFT
:
814 case NS_THEME_WINDOW_FRAME_RIGHT
:
815 case NS_THEME_WINDOW_FRAME_BOTTOM
:
816 case NS_THEME_WINDOW_BUTTON_CLOSE
:
817 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
818 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
819 case NS_THEME_WINDOW_BUTTON_RESTORE
:
820 case NS_THEME_WINDOW_BUTTON_BOX
:
821 case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
:
822 case NS_THEME_WIN_GLASS
:
823 case NS_THEME_WIN_BORDERLESS_GLASS
:
824 return nsUXThemeData::GetTheme(eUXWindowFrame
);
830 nsNativeThemeWin::StandardGetState(nsIFrame
* aFrame
, uint8_t aWidgetType
,
833 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
834 if (eventState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
836 if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
838 if (wantFocused
&& eventState
.HasState(NS_EVENT_STATE_FOCUS
))
845 nsNativeThemeWin::IsMenuActive(nsIFrame
*aFrame
, uint8_t aWidgetType
)
847 nsIContent
* content
= aFrame
->GetContent();
848 if (content
->IsXUL() &&
849 content
->NodeInfo()->Equals(nsGkAtoms::richlistitem
))
850 return CheckBooleanAttr(aFrame
, nsGkAtoms::selected
);
852 return CheckBooleanAttr(aFrame
, nsGkAtoms::menuactive
);
856 * aPart is filled in with the UXTheme part code. On return, values > 0
857 * are the actual UXTheme part code; -1 means the widget will be drawn by
858 * us; 0 means that we should use part code 0, which isn't a real part code
859 * but elicits some kind of default behaviour from UXTheme when drawing
860 * (but isThemeBackgroundPartiallyTransparent may not work).
863 nsNativeThemeWin::GetThemePartAndState(nsIFrame
* aFrame
, uint8_t aWidgetType
,
864 int32_t& aPart
, int32_t& aState
)
866 if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
) {
868 if (aWidgetType
== NS_THEME_DROPDOWN
)
869 aWidgetType
= NS_THEME_TEXTFIELD
;
872 switch (aWidgetType
) {
873 case NS_THEME_BUTTON
: {
880 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
881 if (IsDisabled(aFrame
, eventState
)) {
882 aState
= TS_DISABLED
;
884 } else if (IsOpenButton(aFrame
) ||
885 IsCheckedButton(aFrame
)) {
890 aState
= StandardGetState(aFrame
, aWidgetType
, true);
892 // Check for default dialog buttons. These buttons should always look
894 if (aState
== TS_NORMAL
&& IsDefaultButton(aFrame
))
898 case NS_THEME_CHECKBOX
:
899 case NS_THEME_RADIO
: {
900 bool isCheckbox
= (aWidgetType
== NS_THEME_CHECKBOX
);
901 aPart
= isCheckbox
? BP_CHECKBOX
: BP_RADIO
;
904 UNCHECKED
= 0, CHECKED
, INDETERMINATE
906 InputState inputState
= UNCHECKED
;
907 bool isXULCheckboxRadio
= false;
912 if (GetCheckedOrSelected(aFrame
, !isCheckbox
)) {
913 inputState
= CHECKED
;
914 } if (isCheckbox
&& GetIndeterminate(aFrame
)) {
915 inputState
= INDETERMINATE
;
918 nsEventStates eventState
= GetContentState(isXULCheckboxRadio
? aFrame
->GetParent()
921 if (IsDisabled(aFrame
, eventState
)) {
922 aState
= TS_DISABLED
;
924 aState
= StandardGetState(aFrame
, aWidgetType
, false);
928 // 4 unchecked states, 4 checked states, 4 indeterminate states.
929 aState
+= inputState
* 4;
932 case NS_THEME_GROUPBOX
: {
935 // Since we don't support groupbox disabled and GBS_DISABLED looks the
936 // same as GBS_NORMAL don't bother supporting GBS_DISABLED.
939 case NS_THEME_TEXTFIELD
:
940 case NS_THEME_TEXTFIELD_MULTILINE
: {
941 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
943 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
944 /* Note: the NOSCROLL type has a rounded corner in each
945 * corner. The more specific HSCROLL, VSCROLL, HVSCROLL types
946 * have side and/or top/bottom edges rendered as straight
947 * horizontal lines with sharp corners to accommodate a
948 * scrollbar. However, the scrollbar gets rendered on top of
949 * this for us, so we don't care, and can just use NOSCROLL
952 aPart
= TFP_EDITBORDER_NOSCROLL
;
955 aState
= TFS_EDITBORDER_NORMAL
;
956 } else if (IsDisabled(aFrame
, eventState
)) {
957 aState
= TFS_EDITBORDER_DISABLED
;
958 } else if (IsReadOnly(aFrame
)) {
959 /* no special read-only state */
960 aState
= TFS_EDITBORDER_NORMAL
;
962 nsIContent
* content
= aFrame
->GetContent();
964 /* XUL textboxes don't get focused themselves, because they have child
965 * html:input.. but we can check the XUL focused attributes on them
967 if (content
&& content
->IsXUL() && IsFocused(aFrame
))
968 aState
= TFS_EDITBORDER_FOCUSED
;
969 else if (eventState
.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE
| NS_EVENT_STATE_FOCUS
))
970 aState
= TFS_EDITBORDER_FOCUSED
;
971 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
972 aState
= TFS_EDITBORDER_HOVER
;
974 aState
= TFS_EDITBORDER_NORMAL
;
977 aPart
= TFP_TEXTFIELD
;
981 else if (IsDisabled(aFrame
, eventState
))
982 aState
= TS_DISABLED
;
983 else if (IsReadOnly(aFrame
))
984 aState
= TFS_READONLY
;
986 aState
= StandardGetState(aFrame
, aWidgetType
, true);
991 case NS_THEME_TOOLTIP
: {
992 aPart
= TTP_STANDARD
;
996 case NS_THEME_PROGRESSBAR
:
997 case NS_THEME_PROGRESSBAR_VERTICAL
: {
998 // Note IsVerticalProgress only tests for orient css attrribute,
999 // NS_THEME_PROGRESSBAR_VERTICAL is dedicated to -moz-appearance:
1000 // progressbar-vertical.
1001 bool vertical
= IsVerticalProgress(aFrame
) ||
1002 aWidgetType
== NS_THEME_PROGRESSBAR_VERTICAL
;
1003 aPart
= vertical
? PP_BARVERT
: PP_BAR
;
1004 aState
= PBBS_NORMAL
;
1007 case NS_THEME_PROGRESSBAR_CHUNK
:
1008 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
: {
1009 nsIFrame
* parentFrame
= aFrame
->GetParent();
1010 nsEventStates eventStates
= GetContentState(parentFrame
, aWidgetType
);
1011 if (aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
||
1012 IsVerticalProgress(parentFrame
)) {
1013 aPart
= WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
?
1014 PP_FILLVERT
: PP_CHUNKVERT
;
1016 aPart
= WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
?
1020 aState
= PBBVS_NORMAL
;
1023 case NS_THEME_TOOLBAR_BUTTON
: {
1030 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1031 if (IsDisabled(aFrame
, eventState
)) {
1032 aState
= TS_DISABLED
;
1035 if (IsOpenButton(aFrame
)) {
1040 if (eventState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
1042 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
)) {
1043 if (IsCheckedButton(aFrame
))
1044 aState
= TB_HOVER_CHECKED
;
1049 if (IsCheckedButton(aFrame
))
1050 aState
= TB_CHECKED
;
1057 case NS_THEME_TOOLBAR_SEPARATOR
: {
1058 aPart
= TP_SEPARATOR
;
1062 case NS_THEME_SCROLLBAR_BUTTON_UP
:
1063 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
1064 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
1065 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
: {
1067 aState
= (aWidgetType
- NS_THEME_SCROLLBAR_BUTTON_UP
)*4;
1068 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1070 aState
+= TS_NORMAL
;
1071 else if (IsDisabled(aFrame
, eventState
))
1072 aState
+= TS_DISABLED
;
1074 nsIFrame
*parent
= aFrame
->GetParent();
1075 nsEventStates parentState
= GetContentState(parent
, parent
->StyleDisplay()->mAppearance
);
1076 if (eventState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
1077 aState
+= TS_ACTIVE
;
1078 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
1080 else if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
&&
1081 parentState
.HasState(NS_EVENT_STATE_HOVER
))
1082 aState
= (aWidgetType
- NS_THEME_SCROLLBAR_BUTTON_UP
) + SP_BUTTON_IMPLICIT_HOVER_BASE
;
1084 aState
+= TS_NORMAL
;
1088 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
1089 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
: {
1090 aPart
= (aWidgetType
== NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
) ?
1091 SP_TRACKSTARTHOR
: SP_TRACKSTARTVERT
;
1095 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
1096 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
: {
1097 aPart
= (aWidgetType
== NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
) ?
1098 SP_THUMBHOR
: SP_THUMBVERT
;
1099 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1102 else if (IsDisabled(aFrame
, eventState
))
1103 aState
= TS_DISABLED
;
1105 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
)) // Hover is not also a requirement for
1106 // the thumb, since the drag is not canceled
1107 // when you move outside the thumb.
1109 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
1116 case NS_THEME_RANGE
:
1117 case NS_THEME_SCALE_HORIZONTAL
:
1118 case NS_THEME_SCALE_VERTICAL
: {
1119 if (aWidgetType
== NS_THEME_SCALE_HORIZONTAL
||
1120 (aWidgetType
== NS_THEME_RANGE
&&
1121 IsRangeHorizontal(aFrame
))) {
1123 aState
= TRS_NORMAL
;
1125 aPart
= TKP_TRACKVERT
;
1126 aState
= TRVS_NORMAL
;
1130 case NS_THEME_RANGE_THUMB
:
1131 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
1132 case NS_THEME_SCALE_THUMB_VERTICAL
: {
1133 if (aWidgetType
== NS_THEME_RANGE_THUMB
) {
1134 if (IsRangeHorizontal(aFrame
)) {
1135 aPart
= TKP_THUMBBOTTOM
;
1137 aPart
= IsFrameRTL(aFrame
) ? TKP_THUMBLEFT
: TKP_THUMBRIGHT
;
1140 aPart
= (aWidgetType
== NS_THEME_SCALE_THUMB_HORIZONTAL
) ?
1141 TKP_THUMB
: TKP_THUMBVERT
;
1143 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1146 else if (IsDisabled(aFrame
, eventState
)) {
1147 aState
= TKP_DISABLED
;
1150 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
)) // Hover is not also a requirement for
1151 // the thumb, since the drag is not canceled
1152 // when you move outside the thumb.
1154 else if (eventState
.HasState(NS_EVENT_STATE_FOCUS
))
1155 aState
= TKP_FOCUSED
;
1156 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
1163 case NS_THEME_SPINNER_UP_BUTTON
:
1164 case NS_THEME_SPINNER_DOWN_BUTTON
: {
1165 aPart
= (aWidgetType
== NS_THEME_SPINNER_UP_BUTTON
) ?
1166 SPNP_UP
: SPNP_DOWN
;
1167 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1170 else if (IsDisabled(aFrame
, eventState
))
1171 aState
= TS_DISABLED
;
1173 aState
= StandardGetState(aFrame
, aWidgetType
, false);
1176 case NS_THEME_TOOLBOX
:
1177 case NS_THEME_WIN_MEDIA_TOOLBOX
:
1178 case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX
:
1179 case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX
:
1180 case NS_THEME_STATUSBAR
:
1181 case NS_THEME_SCROLLBAR
:
1182 case NS_THEME_SCROLLBAR_SMALL
: {
1184 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
1185 // On vista, they have a part
1186 aPart
= RP_BACKGROUND
;
1188 // Otherwise, they don't. (But I bet
1189 // RP_BACKGROUND would work here, too);
1194 case NS_THEME_TOOLBAR
: {
1195 // Use -1 to indicate we don't wish to have the theme background drawn
1196 // for this item. We will pass any nessessary information via aState,
1197 // and will render the item using separate code.
1201 nsIContent
* content
= aFrame
->GetContent();
1202 nsIContent
* parent
= content
->GetParent();
1203 // XXXzeniko hiding the first toolbar will result in an unwanted margin
1204 if (parent
&& parent
->GetFirstChild() == content
) {
1210 case NS_THEME_STATUSBAR_PANEL
:
1211 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
1212 case NS_THEME_RESIZER
: {
1213 aPart
= (aWidgetType
- NS_THEME_STATUSBAR_PANEL
) + 1;
1217 case NS_THEME_TREEVIEW
:
1218 case NS_THEME_LISTBOX
: {
1219 aPart
= TREEVIEW_BODY
;
1223 case NS_THEME_TAB_PANELS
: {
1224 aPart
= TABP_PANELS
;
1228 case NS_THEME_TAB_PANEL
: {
1233 case NS_THEME_TAB
: {
1240 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1241 if (IsDisabled(aFrame
, eventState
)) {
1242 aState
= TS_DISABLED
;
1246 if (IsSelectedTab(aFrame
)) {
1247 aPart
= TABP_TAB_SELECTED
;
1248 aState
= TS_ACTIVE
; // The selected tab is always "pressed".
1251 aState
= StandardGetState(aFrame
, aWidgetType
, true);
1255 case NS_THEME_TREEVIEW_HEADER_SORTARROW
: {
1256 // XXX Probably will never work due to a bug in the Luna theme.
1261 case NS_THEME_TREEVIEW_HEADER_CELL
: {
1268 aState
= StandardGetState(aFrame
, aWidgetType
, true);
1272 case NS_THEME_DROPDOWN
: {
1273 nsIContent
* content
= aFrame
->GetContent();
1274 bool isHTML
= content
&& content
->IsHTML();
1275 bool useDropBorder
= isHTML
|| IsMenuListEditable(aFrame
);
1276 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1278 /* On Vista/Win7, we use CBP_DROPBORDER instead of DROPFRAME for HTML
1279 * content or for editable menulists; this gives us the thin outline,
1280 * instead of the gradient-filled background */
1282 aPart
= CBP_DROPBORDER
;
1284 aPart
= CBP_DROPFRAME
;
1286 if (IsDisabled(aFrame
, eventState
)) {
1287 aState
= TS_DISABLED
;
1288 } else if (IsReadOnly(aFrame
)) {
1290 } else if (IsOpenButton(aFrame
)) {
1293 if (useDropBorder
&& (eventState
.HasState(NS_EVENT_STATE_FOCUS
) || IsFocused(aFrame
)))
1295 else if (eventState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
1297 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
))
1305 case NS_THEME_DROPDOWN_BUTTON
: {
1306 bool isHTML
= IsHTMLContent(aFrame
);
1307 nsIFrame
* parentFrame
= aFrame
->GetParent();
1308 bool isMenulist
= !isHTML
&& parentFrame
->GetType() == nsGkAtoms::menuFrame
;
1309 bool isOpen
= false;
1311 // HTML select and XUL menulist dropdown buttons get state from the parent.
1312 if (isHTML
|| isMenulist
)
1313 aFrame
= parentFrame
;
1315 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1316 aPart
= WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
?
1317 CBP_DROPMARKER_VISTA
: CBP_DROPMARKER
;
1319 // For HTML controls with author styling, we should fall
1320 // back to the old dropmarker style to avoid clashes with
1321 // author-specified backgrounds and borders (bug #441034)
1322 if (isHTML
&& IsWidgetStyled(aFrame
->PresContext(), aFrame
, NS_THEME_DROPDOWN
))
1323 aPart
= CBP_DROPMARKER
;
1325 if (IsDisabled(aFrame
, eventState
)) {
1326 aState
= TS_DISABLED
;
1331 nsIComboboxControlFrame
* ccf
= do_QueryFrame(aFrame
);
1332 isOpen
= (ccf
&& ccf
->IsDroppedDown());
1335 isOpen
= IsOpenButton(aFrame
);
1337 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
1338 if (isHTML
|| IsMenuListEditable(aFrame
)) {
1340 /* Hover is propagated, but we need to know whether we're
1341 * hovering just the combobox frame, not the dropdown frame.
1342 * But, we can't get that information, since hover is on the
1343 * content node, and they share the same content node. So,
1344 * instead, we cheat -- if the dropdown is open, we always
1345 * show the hover state. This looks fine in practice.
1351 /* On Vista, the dropdown indicator on a menulist button in
1352 * chrome is not given a hover effect. When the frame isn't
1353 * isn't HTML content, we cheat and force the dropdown state
1354 * to be normal. (Bug 430434)
1363 // Dropdown button active state doesn't need :hover.
1364 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
)) {
1365 if (isOpen
&& (isHTML
|| isMenulist
)) {
1366 // XXX Button should look active until the mouse is released, but
1367 // without making it look active when the popup is clicked.
1372 else if (eventState
.HasState(NS_EVENT_STATE_HOVER
)) {
1373 // No hover effect for XUL menulists and autocomplete dropdown buttons
1374 // while the dropdown menu is open.
1376 // XXX HTML select dropdown buttons should have the hover effect when
1377 // hovering the combobox frame, but not the popup frame.
1384 case NS_THEME_MENUPOPUP
: {
1385 aPart
= MENU_POPUPBACKGROUND
;
1389 case NS_THEME_MENUITEM
:
1390 case NS_THEME_CHECKMENUITEM
:
1391 case NS_THEME_RADIOMENUITEM
: {
1392 bool isTopLevel
= false;
1393 bool isOpen
= false;
1394 bool isHover
= false;
1395 nsMenuFrame
*menuFrame
= do_QueryFrame(aFrame
);
1396 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1398 isTopLevel
= IsTopLevelMenu(aFrame
);
1401 isOpen
= menuFrame
->IsOpen();
1403 isHover
= IsMenuActive(aFrame
, aWidgetType
);
1406 aPart
= MENU_BARITEM
;
1409 aState
= MBI_PUSHED
;
1413 aState
= MBI_NORMAL
;
1415 // the disabled states are offset by 3
1416 if (IsDisabled(aFrame
, eventState
))
1419 aPart
= MENU_POPUPITEM
;
1424 aState
= MPI_NORMAL
;
1426 // the disabled states are offset by 2
1427 if (IsDisabled(aFrame
, eventState
))
1433 case NS_THEME_MENUSEPARATOR
:
1434 aPart
= MENU_POPUPSEPARATOR
;
1437 case NS_THEME_MENUARROW
:
1439 aPart
= MENU_POPUPSUBMENU
;
1440 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1441 aState
= IsDisabled(aFrame
, eventState
) ? MSM_DISABLED
: MSM_NORMAL
;
1444 case NS_THEME_MENUCHECKBOX
:
1445 case NS_THEME_MENURADIO
:
1448 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1450 // NOTE: we can probably use NS_EVENT_STATE_CHECKED
1451 isChecked
= CheckBooleanAttr(aFrame
, nsGkAtoms::checked
);
1453 aPart
= MENU_POPUPCHECK
;
1454 aState
= MC_CHECKMARKNORMAL
;
1456 // Radio states are offset by 2
1457 if (aWidgetType
== NS_THEME_MENURADIO
)
1460 // the disabled states are offset by 1
1461 if (IsDisabled(aFrame
, eventState
))
1466 case NS_THEME_MENUITEMTEXT
:
1467 case NS_THEME_MENUIMAGE
:
1472 case NS_THEME_WINDOW_TITLEBAR
:
1473 aPart
= mozilla::widget::themeconst::WP_CAPTION
;
1474 aState
= GetTopLevelWindowActiveState(aFrame
);
1476 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
1477 aPart
= mozilla::widget::themeconst::WP_MAXCAPTION
;
1478 aState
= GetTopLevelWindowActiveState(aFrame
);
1480 case NS_THEME_WINDOW_FRAME_LEFT
:
1481 aPart
= mozilla::widget::themeconst::WP_FRAMELEFT
;
1482 aState
= GetTopLevelWindowActiveState(aFrame
);
1484 case NS_THEME_WINDOW_FRAME_RIGHT
:
1485 aPart
= mozilla::widget::themeconst::WP_FRAMERIGHT
;
1486 aState
= GetTopLevelWindowActiveState(aFrame
);
1488 case NS_THEME_WINDOW_FRAME_BOTTOM
:
1489 aPart
= mozilla::widget::themeconst::WP_FRAMEBOTTOM
;
1490 aState
= GetTopLevelWindowActiveState(aFrame
);
1492 case NS_THEME_WINDOW_BUTTON_CLOSE
:
1493 aPart
= mozilla::widget::themeconst::WP_CLOSEBUTTON
;
1494 aState
= GetWindowFrameButtonState(aFrame
, GetContentState(aFrame
, aWidgetType
));
1496 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
1497 aPart
= mozilla::widget::themeconst::WP_MINBUTTON
;
1498 aState
= GetWindowFrameButtonState(aFrame
, GetContentState(aFrame
, aWidgetType
));
1500 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
1501 aPart
= mozilla::widget::themeconst::WP_MAXBUTTON
;
1502 aState
= GetWindowFrameButtonState(aFrame
, GetContentState(aFrame
, aWidgetType
));
1504 case NS_THEME_WINDOW_BUTTON_RESTORE
:
1505 aPart
= mozilla::widget::themeconst::WP_RESTOREBUTTON
;
1506 aState
= GetWindowFrameButtonState(aFrame
, GetContentState(aFrame
, aWidgetType
));
1508 case NS_THEME_WINDOW_BUTTON_BOX
:
1509 case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
:
1510 case NS_THEME_WIN_GLASS
:
1511 case NS_THEME_WIN_BORDERLESS_GLASS
:
1519 return NS_ERROR_FAILURE
;
1523 AssumeThemePartAndStateAreTransparent(int32_t aPart
, int32_t aState
)
1525 if (aPart
== MENU_POPUPITEM
&& aState
== MBI_NORMAL
) {
1532 nsNativeThemeWin::DrawWidgetBackground(nsRenderingContext
* aContext
,
1534 uint8_t aWidgetType
,
1535 const nsRect
& aRect
,
1536 const nsRect
& aDirtyRect
)
1538 HANDLE theme
= GetTheme(aWidgetType
);
1540 return ClassicDrawWidgetBackground(aContext
, aFrame
, aWidgetType
, aRect
, aDirtyRect
);
1542 // ^^ without the right sdk, assume xp theming and fall through.
1543 if (nsUXThemeData::CheckForCompositor()) {
1544 switch (aWidgetType
) {
1545 case NS_THEME_WINDOW_TITLEBAR
:
1546 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
1547 case NS_THEME_WINDOW_FRAME_LEFT
:
1548 case NS_THEME_WINDOW_FRAME_RIGHT
:
1549 case NS_THEME_WINDOW_FRAME_BOTTOM
:
1550 // Nothing to draw, these areas are glass. Minimum dimensions
1551 // should be set, so xul content should be layed out correctly.
1554 case NS_THEME_WINDOW_BUTTON_CLOSE
:
1555 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
1556 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
1557 case NS_THEME_WINDOW_BUTTON_RESTORE
:
1558 // Not conventional bitmaps, can't be retrieved. If we fall
1559 // through here and call the theme library we'll get aero
1563 case NS_THEME_WIN_GLASS
:
1564 case NS_THEME_WIN_BORDERLESS_GLASS
:
1565 // Nothing to draw, this is the glass background.
1571 int32_t part
, state
;
1572 nsresult rv
= GetThemePartAndState(aFrame
, aWidgetType
, part
, state
);
1576 if (AssumeThemePartAndStateAreTransparent(part
, state
)) {
1580 gfxFloat p2a
= gfxFloat(aContext
->AppUnitsPerDevPixel());
1583 gfxRect
tr(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
),
1584 dr(aDirtyRect
.x
, aDirtyRect
.y
, aDirtyRect
.width
, aDirtyRect
.height
);
1586 tr
.ScaleInverse(p2a
);
1587 dr
.ScaleInverse(p2a
);
1589 /* See GetWidgetOverflow */
1590 if (aWidgetType
== NS_THEME_DROPDOWN_BUTTON
&&
1591 part
== CBP_DROPMARKER_VISTA
&& IsHTMLContent(aFrame
))
1601 if (IsFrameRTL(aFrame
)) {
1607 nsRefPtr
<gfxContext
> ctx
= aContext
->ThebesContext();
1609 gfxWindowsNativeDrawing
nativeDrawing(ctx
, dr
, GetWidgetNativeDrawingFlags(aWidgetType
));
1613 HDC hdc
= nativeDrawing
.BeginNativeDrawing();
1615 return NS_ERROR_FAILURE
;
1617 nativeDrawing
.TransformToNativeRect(tr
, widgetRect
);
1618 nativeDrawing
.TransformToNativeRect(dr
, clipRect
);
1622 PR_LOG(gWindowsLog
, PR_LOG_ERROR
,
1623 (stderr
, "xform: %f %f %f %f [%f %f]\n", m
.xx
, m
.yx
, m
.xy
, m
.yy
,
1625 PR_LOG(gWindowsLog
, PR_LOG_ERROR
,
1626 (stderr
, "tr: [%d %d %d %d]\ndr: [%d %d %d %d]\noff: [%f %f]\n",
1627 tr
.x
, tr
.y
, tr
.width
, tr
.height
, dr
.x
, dr
.y
, dr
.width
, dr
.height
,
1628 offset
.x
, offset
.y
));
1632 if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR
) {
1633 // Clip out the left and right corners of the frame, all we want in
1634 // is the middle section.
1635 widgetRect
.left
-= GetSystemMetrics(SM_CXFRAME
);
1636 widgetRect
.right
+= GetSystemMetrics(SM_CXFRAME
);
1637 } else if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
) {
1638 // The origin of the window is off screen when maximized and windows
1639 // doesn't compensate for this in rendering the background. Push the
1640 // top of the bitmap down by SM_CYFRAME so we get the full graphic.
1641 widgetRect
.top
+= GetSystemMetrics(SM_CYFRAME
);
1642 } else if (aWidgetType
== NS_THEME_TAB
) {
1643 // For left edge and right edge tabs, we need to adjust the widget
1644 // rects and clip rects so that the edges don't get drawn.
1645 bool isLeft
= IsLeftToSelectedTab(aFrame
);
1646 bool isRight
= !isLeft
&& IsRightToSelectedTab(aFrame
);
1648 if (isLeft
|| isRight
) {
1649 // HACK ALERT: There appears to be no way to really obtain this value, so we're forced
1650 // to just use the default value for Luna (which also happens to be correct for
1651 // all the other skins I've tried).
1652 int32_t edgeSize
= 2;
1654 // Armed with the size of the edge, we now need to either shift to the left or to the
1655 // right. The clip rect won't include this extra area, so we know that we're
1656 // effectively shifting the edge out of view (such that it won't be painted).
1658 // The right edge should not be drawn. Extend our rect by the edge size.
1659 widgetRect
.right
+= edgeSize
;
1661 // The left edge should not be drawn. Move the widget rect's left coord back.
1662 widgetRect
.left
-= edgeSize
;
1665 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MINIMIZE
) {
1666 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_MINIMIZE
);
1668 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MAXIMIZE
||
1669 aWidgetType
== NS_THEME_WINDOW_BUTTON_RESTORE
) {
1670 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_RESTORE
);
1672 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_CLOSE
) {
1673 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_CLOSE
);
1676 // widgetRect is the bounding box for a widget, yet the scale track is only
1677 // a small portion of this size, so the edges of the scale need to be
1678 // adjusted to the real size of the track.
1679 if (aWidgetType
== NS_THEME_RANGE
||
1680 aWidgetType
== NS_THEME_SCALE_HORIZONTAL
||
1681 aWidgetType
== NS_THEME_SCALE_VERTICAL
) {
1683 GetThemeBackgroundContentRect(theme
, hdc
, part
, state
, &widgetRect
, &contentRect
);
1686 GetThemePartSize(theme
, hdc
, part
, state
, &widgetRect
, TS_TRUE
, &siz
);
1688 // When rounding is necessary, we round the position of the track
1689 // away from the chevron of the thumb to make it look better.
1690 if (aWidgetType
== NS_THEME_SCALE_HORIZONTAL
||
1691 (aWidgetType
== NS_THEME_RANGE
&& IsRangeHorizontal(aFrame
))) {
1692 contentRect
.top
+= (contentRect
.bottom
- contentRect
.top
- siz
.cy
) / 2;
1693 contentRect
.bottom
= contentRect
.top
+ siz
.cy
;
1696 if (!IsFrameRTL(aFrame
)) {
1697 contentRect
.left
+= (contentRect
.right
- contentRect
.left
- siz
.cx
) / 2;
1698 contentRect
.right
= contentRect
.left
+ siz
.cx
;
1700 contentRect
.right
-= (contentRect
.right
- contentRect
.left
- siz
.cx
) / 2;
1701 contentRect
.left
= contentRect
.right
- siz
.cx
;
1705 DrawThemeBackground(theme
, hdc
, part
, state
, &contentRect
, &clipRect
);
1707 else if (aWidgetType
== NS_THEME_MENUCHECKBOX
|| aWidgetType
== NS_THEME_MENURADIO
)
1709 bool isChecked
= false;
1710 isChecked
= CheckBooleanAttr(aFrame
, nsGkAtoms::checked
);
1714 int bgState
= MCB_NORMAL
;
1715 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
1717 // the disabled states are offset by 1
1718 if (IsDisabled(aFrame
, eventState
))
1721 SIZE
checkboxBGSize(GetCheckboxBGSize(theme
, hdc
));
1723 RECT checkBGRect
= widgetRect
;
1724 if (IsFrameRTL(aFrame
)) {
1725 checkBGRect
.left
= checkBGRect
.right
-checkboxBGSize
.cx
;
1727 checkBGRect
.right
= checkBGRect
.left
+checkboxBGSize
.cx
;
1730 // Center the checkbox background vertically in the menuitem
1731 checkBGRect
.top
+= (checkBGRect
.bottom
- checkBGRect
.top
)/2 - checkboxBGSize
.cy
/2;
1732 checkBGRect
.bottom
= checkBGRect
.top
+ checkboxBGSize
.cy
;
1734 DrawThemeBackground(theme
, hdc
, MENU_POPUPCHECKBACKGROUND
, bgState
, &checkBGRect
, &clipRect
);
1736 MARGINS checkMargins
= GetCheckboxMargins(theme
, hdc
);
1737 RECT checkRect
= checkBGRect
;
1738 checkRect
.left
+= checkMargins
.cxLeftWidth
;
1739 checkRect
.right
-= checkMargins
.cxRightWidth
;
1740 checkRect
.top
+= checkMargins
.cyTopHeight
;
1741 checkRect
.bottom
-= checkMargins
.cyBottomHeight
;
1742 DrawThemeBackground(theme
, hdc
, MENU_POPUPCHECK
, state
, &checkRect
, &clipRect
);
1745 else if (aWidgetType
== NS_THEME_MENUPOPUP
)
1747 DrawThemeBackground(theme
, hdc
, MENU_POPUPBORDERS
, /* state */ 0, &widgetRect
, &clipRect
);
1749 GetThemePartSize(theme
, hdc
, MENU_POPUPBORDERS
, 0, nullptr, TS_TRUE
, &borderSize
);
1751 RECT bgRect
= widgetRect
;
1752 bgRect
.top
+= borderSize
.cy
;
1753 bgRect
.bottom
-= borderSize
.cy
;
1754 bgRect
.left
+= borderSize
.cx
;
1755 bgRect
.right
-= borderSize
.cx
;
1757 DrawThemeBackground(theme
, hdc
, MENU_POPUPBACKGROUND
, /* state */ 0, &bgRect
, &clipRect
);
1759 SIZE
gutterSize(GetGutterSize(theme
, hdc
));
1762 gutterRect
.top
= bgRect
.top
;
1763 gutterRect
.bottom
= bgRect
.bottom
;
1764 if (IsFrameRTL(aFrame
)) {
1765 gutterRect
.right
= bgRect
.right
;
1766 gutterRect
.left
= gutterRect
.right
-gutterSize
.cx
;
1768 gutterRect
.left
= bgRect
.left
;
1769 gutterRect
.right
= gutterRect
.left
+gutterSize
.cx
;
1772 DrawThemeBGRTLAware(theme
, hdc
, MENU_POPUPGUTTER
, /* state */ 0,
1773 &gutterRect
, &clipRect
, IsFrameRTL(aFrame
));
1775 else if (aWidgetType
== NS_THEME_MENUSEPARATOR
)
1777 SIZE
gutterSize(GetGutterSize(theme
,hdc
));
1779 RECT sepRect
= widgetRect
;
1780 if (IsFrameRTL(aFrame
))
1781 sepRect
.right
-= gutterSize
.cx
;
1783 sepRect
.left
+= gutterSize
.cx
;
1785 DrawThemeBackground(theme
, hdc
, MENU_POPUPSEPARATOR
, /* state */ 0, &sepRect
, &clipRect
);
1787 // The following widgets need to be RTL-aware
1788 else if (aWidgetType
== NS_THEME_MENUARROW
||
1789 aWidgetType
== NS_THEME_RESIZER
||
1790 aWidgetType
== NS_THEME_DROPDOWN_BUTTON
)
1792 DrawThemeBGRTLAware(theme
, hdc
, part
, state
,
1793 &widgetRect
, &clipRect
, IsFrameRTL(aFrame
));
1795 else if (aWidgetType
== NS_THEME_PROGRESSBAR
||
1796 aWidgetType
== NS_THEME_PROGRESSBAR_VERTICAL
) {
1797 // DrawThemeBackground renders each corner with a solid white pixel.
1798 // Restore these pixels to the underlying color. Tracks are rendered
1799 // using alpha recovery, so this makes the corners transparent.
1801 color
= GetPixel(hdc
, widgetRect
.left
, widgetRect
.top
);
1802 DrawThemeBackground(theme
, hdc
, part
, state
, &widgetRect
, &clipRect
);
1803 SetPixel(hdc
, widgetRect
.left
, widgetRect
.top
, color
);
1804 SetPixel(hdc
, widgetRect
.right
-1, widgetRect
.top
, color
);
1805 SetPixel(hdc
, widgetRect
.right
-1, widgetRect
.bottom
-1, color
);
1806 SetPixel(hdc
, widgetRect
.left
, widgetRect
.bottom
-1, color
);
1808 else if (aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK
||
1809 aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
) {
1810 DrawThemedProgressMeter(aFrame
, aWidgetType
, theme
, hdc
, part
, state
,
1811 &widgetRect
, &clipRect
, p2a
);
1813 // If part is negative, the element wishes us to not render a themed
1814 // background, instead opting to be drawn specially below.
1815 else if (part
>= 0) {
1816 DrawThemeBackground(theme
, hdc
, part
, state
, &widgetRect
, &clipRect
);
1819 // Draw focus rectangles for XP HTML checkboxes and radio buttons
1820 // XXX it'd be nice to draw these outside of the frame
1821 if (((aWidgetType
== NS_THEME_CHECKBOX
|| aWidgetType
== NS_THEME_RADIO
) &&
1822 aFrame
->GetContent()->IsHTML()) ||
1823 aWidgetType
== NS_THEME_RANGE
||
1824 aWidgetType
== NS_THEME_SCALE_HORIZONTAL
||
1825 aWidgetType
== NS_THEME_SCALE_VERTICAL
) {
1826 nsEventStates contentState
= GetContentState(aFrame
, aWidgetType
);
1828 if (contentState
.HasState(NS_EVENT_STATE_FOCUS
)) {
1830 HPEN hPen
= nullptr;
1832 uint8_t id
= SaveDC(hdc
);
1834 ::SelectClipRgn(hdc
, nullptr);
1835 ::GetViewportOrgEx(hdc
, &vpOrg
);
1836 ::SetBrushOrgEx(hdc
, vpOrg
.x
+ widgetRect
.left
, vpOrg
.y
+ widgetRect
.top
, nullptr);
1838 // On vista, choose our own colors and draw an XP style half focus rect
1839 // for focused checkboxes and a full rect when active.
1840 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
&&
1841 aWidgetType
== NS_THEME_CHECKBOX
) {
1843 lb
.lbStyle
= BS_SOLID
;
1844 lb
.lbColor
= RGB(255,255,255);
1847 hPen
= ::ExtCreatePen(PS_COSMETIC
|PS_ALTERNATE
, 1, &lb
, 0, nullptr);
1848 ::SelectObject(hdc
, hPen
);
1850 // If pressed, draw the upper left corner of the dotted rect.
1851 if (contentState
.HasState(NS_EVENT_STATE_ACTIVE
)) {
1852 ::MoveToEx(hdc
, widgetRect
.left
, widgetRect
.bottom
-1, nullptr);
1853 ::LineTo(hdc
, widgetRect
.left
, widgetRect
.top
);
1854 ::LineTo(hdc
, widgetRect
.right
-1, widgetRect
.top
);
1857 // Draw the lower right corner of the dotted rect.
1858 ::MoveToEx(hdc
, widgetRect
.right
-1, widgetRect
.top
, nullptr);
1859 ::LineTo(hdc
, widgetRect
.right
-1, widgetRect
.bottom
-1);
1860 ::LineTo(hdc
, widgetRect
.left
, widgetRect
.bottom
-1);
1862 ::SetTextColor(hdc
, 0);
1863 ::DrawFocusRect(hdc
, &widgetRect
);
1865 ::RestoreDC(hdc
, id
);
1867 ::DeleteObject(hPen
);
1871 else if (aWidgetType
== NS_THEME_TOOLBAR
&& state
== 0) {
1872 // Draw toolbar separator lines above all toolbars except the first one.
1873 // The lines are part of the Rebar theme, which is loaded for NS_THEME_TOOLBOX.
1874 theme
= GetTheme(NS_THEME_TOOLBOX
);
1876 return NS_ERROR_FAILURE
;
1878 widgetRect
.bottom
= widgetRect
.top
+ TB_SEPARATOR_HEIGHT
;
1879 DrawThemeEdge(theme
, hdc
, RP_BAND
, 0, &widgetRect
, EDGE_ETCHED
, BF_TOP
, nullptr);
1881 else if (aWidgetType
== NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
||
1882 aWidgetType
== NS_THEME_SCROLLBAR_THUMB_VERTICAL
)
1884 // Draw the decorative gripper for the scrollbar thumb button, if it fits
1888 int gripPart
= (aWidgetType
== NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
) ?
1889 SP_GRIPPERHOR
: SP_GRIPPERVERT
;
1891 if (GetThemePartSize(theme
, hdc
, gripPart
, state
, nullptr, TS_TRUE
, &gripSize
) == S_OK
&&
1892 GetThemeMargins(theme
, hdc
, part
, state
, TMT_CONTENTMARGINS
, nullptr, &thumbMgns
) == S_OK
&&
1893 gripSize
.cx
+ thumbMgns
.cxLeftWidth
+ thumbMgns
.cxRightWidth
<= widgetRect
.right
- widgetRect
.left
&&
1894 gripSize
.cy
+ thumbMgns
.cyTopHeight
+ thumbMgns
.cyBottomHeight
<= widgetRect
.bottom
- widgetRect
.top
)
1896 DrawThemeBackground(theme
, hdc
, gripPart
, state
, &widgetRect
, &clipRect
);
1899 else if ((aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX
||
1900 aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
) &&
1901 nsUXThemeData::CheckForCompositor())
1903 // The caption buttons are drawn by the DWM, we just need to clear the area where they
1904 // are because we might have drawn something above them (like a background-image).
1907 ctx
->Translate(dr
.TopLeft());
1909 // Create a rounded rectangle to follow the buttons' look.
1910 gfxRect
buttonbox1(0.0, 0.0, dr
.Width(), dr
.Height() - 2.0);
1911 gfxRect
buttonbox2(1.0, dr
.Height() - 2.0, dr
.Width() - 1.0, 1.0);
1912 gfxRect
buttonbox3(2.0, dr
.Height() - 1.0, dr
.Width() - 3.0, 1.0);
1914 gfxContext::GraphicsOperator currentOp
= ctx
->CurrentOperator();
1915 ctx
->SetOperator(gfxContext::OPERATOR_CLEAR
);
1917 // Each rectangle is drawn individually because OPERATOR_CLEAR takes
1918 // the fallback path to cairo_d2d_acquire_dest if the area to fill
1919 // is a complex region.
1921 ctx
->Rectangle(buttonbox1
, true);
1925 ctx
->Rectangle(buttonbox2
, true);
1929 ctx
->Rectangle(buttonbox3
, true);
1933 ctx
->SetOperator(currentOp
);
1936 nativeDrawing
.EndNativeDrawing();
1938 if (nativeDrawing
.ShouldRenderAgain())
1941 nativeDrawing
.PaintToContext();
1947 nsNativeThemeWin::GetWidgetBorder(nsDeviceContext
* aContext
,
1949 uint8_t aWidgetType
,
1950 nsIntMargin
* aResult
)
1952 HANDLE theme
= GetTheme(aWidgetType
);
1954 return ClassicGetWidgetBorder(aContext
, aFrame
, aWidgetType
, aResult
);
1956 (*aResult
).top
= (*aResult
).bottom
= (*aResult
).left
= (*aResult
).right
= 0;
1958 if (!WidgetIsContainer(aWidgetType
) ||
1959 aWidgetType
== NS_THEME_TOOLBOX
||
1960 aWidgetType
== NS_THEME_WIN_MEDIA_TOOLBOX
||
1961 aWidgetType
== NS_THEME_WIN_COMMUNICATIONS_TOOLBOX
||
1962 aWidgetType
== NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX
||
1963 aWidgetType
== NS_THEME_STATUSBAR
||
1964 aWidgetType
== NS_THEME_RESIZER
|| aWidgetType
== NS_THEME_TAB_PANEL
||
1965 aWidgetType
== NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
||
1966 aWidgetType
== NS_THEME_SCROLLBAR_TRACK_VERTICAL
||
1967 aWidgetType
== NS_THEME_MENUITEM
|| aWidgetType
== NS_THEME_CHECKMENUITEM
||
1968 aWidgetType
== NS_THEME_RADIOMENUITEM
|| aWidgetType
== NS_THEME_MENUPOPUP
||
1969 aWidgetType
== NS_THEME_MENUIMAGE
|| aWidgetType
== NS_THEME_MENUITEMTEXT
||
1970 aWidgetType
== NS_THEME_TOOLBAR_SEPARATOR
||
1971 aWidgetType
== NS_THEME_WINDOW_TITLEBAR
||
1972 aWidgetType
== NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
||
1973 aWidgetType
== NS_THEME_WIN_GLASS
|| aWidgetType
== NS_THEME_WIN_BORDERLESS_GLASS
)
1974 return NS_OK
; // Don't worry about it.
1976 int32_t part
, state
;
1977 nsresult rv
= GetThemePartAndState(aFrame
, aWidgetType
, part
, state
);
1981 if (aWidgetType
== NS_THEME_TOOLBAR
) {
1982 // make space for the separator line above all toolbars but the first
1984 aResult
->top
= TB_SEPARATOR_HEIGHT
;
1989 RECT outerRect
; // Create a fake outer rect.
1990 outerRect
.top
= outerRect
.left
= 100;
1991 outerRect
.right
= outerRect
.bottom
= 200;
1992 RECT
contentRect(outerRect
);
1993 HRESULT res
= GetThemeBackgroundContentRect(theme
, nullptr, part
, state
, &outerRect
, &contentRect
);
1996 return NS_ERROR_FAILURE
;
1998 // Now compute the delta in each direction and place it in our
1999 // nsIntMargin struct.
2000 aResult
->top
= contentRect
.top
- outerRect
.top
;
2001 aResult
->bottom
= outerRect
.bottom
- contentRect
.bottom
;
2002 aResult
->left
= contentRect
.left
- outerRect
.left
;
2003 aResult
->right
= outerRect
.right
- contentRect
.right
;
2005 // Remove the edges for tabs that are before or after the selected tab,
2006 if (aWidgetType
== NS_THEME_TAB
) {
2007 if (IsLeftToSelectedTab(aFrame
))
2008 // Remove the right edge, since we won't be drawing it.
2010 else if (IsRightToSelectedTab(aFrame
))
2011 // Remove the left edge, since we won't be drawing it.
2015 if (aFrame
&& (aWidgetType
== NS_THEME_TEXTFIELD
|| aWidgetType
== NS_THEME_TEXTFIELD_MULTILINE
)) {
2016 nsIContent
* content
= aFrame
->GetContent();
2017 if (content
&& content
->IsHTML()) {
2018 // We need to pad textfields by 1 pixel, since the caret will draw
2019 // flush against the edge by default if we don't.
2031 nsNativeThemeWin::GetWidgetPadding(nsDeviceContext
* aContext
,
2033 uint8_t aWidgetType
,
2034 nsIntMargin
* aResult
)
2036 switch (aWidgetType
) {
2037 // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
2038 // and have a meaningful baseline, so they can't have
2039 // author-specified padding.
2040 case NS_THEME_CHECKBOX
:
2041 case NS_THEME_RADIO
:
2042 aResult
->SizeTo(0, 0, 0, 0);
2046 HANDLE theme
= GetTheme(aWidgetType
);
2048 if (aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX
||
2049 aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
) {
2050 aResult
->SizeTo(0, 0, 0, 0);
2052 // aero glass doesn't display custom buttons
2053 if (nsUXThemeData::CheckForCompositor())
2056 // button padding for standard windows
2057 if (aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX
) {
2058 aResult
->top
= GetSystemMetrics(SM_CXFRAME
);
2064 if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR
||
2065 aWidgetType
== NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
) {
2066 aResult
->SizeTo(0, 0, 0, 0);
2067 // XXX Maximized windows have an offscreen offset equal to
2068 // the border padding. This should be addressed in nsWindow,
2069 // but currently can't be, see UpdateNonClientMargins.
2070 if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
)
2071 aResult
->top
= GetSystemMetrics(SM_CXFRAME
)
2072 + GetSystemMetrics(SM_CXPADDEDBORDER
);
2077 return ClassicGetWidgetPadding(aContext
, aFrame
, aWidgetType
, aResult
);
2079 if (aWidgetType
== NS_THEME_MENUPOPUP
)
2082 GetThemePartSize(theme
, nullptr, MENU_POPUPBORDERS
, /* state */ 0, nullptr, TS_TRUE
, &popupSize
);
2083 aResult
->top
= aResult
->bottom
= popupSize
.cy
;
2084 aResult
->left
= aResult
->right
= popupSize
.cx
;
2088 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
2089 if (aWidgetType
== NS_THEME_TEXTFIELD
||
2090 aWidgetType
== NS_THEME_TEXTFIELD_MULTILINE
||
2091 aWidgetType
== NS_THEME_DROPDOWN
)
2093 /* If we have author-specified padding for these elements, don't do the fixups below */
2094 if (aFrame
->PresContext()->HasAuthorSpecifiedRules(aFrame
, NS_AUTHOR_SPECIFIED_PADDING
))
2098 /* textfields need extra pixels on all sides, otherwise they
2099 * wrap their content too tightly. The actual border is drawn 1px
2100 * inside the specified rectangle, so Gecko will end up making the
2101 * contents look too small. Instead, we add 2px padding for the
2102 * contents and fix this. (Used to be 1px added, see bug 430212)
2104 if (aWidgetType
== NS_THEME_TEXTFIELD
|| aWidgetType
== NS_THEME_TEXTFIELD_MULTILINE
) {
2105 aResult
->top
= aResult
->bottom
= 2;
2106 aResult
->left
= aResult
->right
= 2;
2108 } else if (IsHTMLContent(aFrame
) && aWidgetType
== NS_THEME_DROPDOWN
) {
2109 /* For content menulist controls, we need an extra pixel so
2110 * that we have room to draw our focus rectangle stuff.
2111 * Otherwise, the focus rect might overlap the control's
2114 aResult
->top
= aResult
->bottom
= 1;
2115 aResult
->left
= aResult
->right
= 1;
2120 int32_t right
, left
, top
, bottom
;
2121 right
= left
= top
= bottom
= 0;
2122 switch (aWidgetType
)
2124 case NS_THEME_MENUIMAGE
:
2128 case NS_THEME_MENUCHECKBOX
:
2129 case NS_THEME_MENURADIO
:
2133 case NS_THEME_MENUITEMTEXT
:
2134 // There seem to be exactly 4 pixels from the edge
2135 // of the gutter to the text: 2px margin (CSS) + 2px padding (here)
2137 SIZE
size(GetGutterSize(theme
, nullptr));
2141 case NS_THEME_MENUSEPARATOR
:
2143 SIZE
size(GetGutterSize(theme
, nullptr));
2153 if (IsFrameRTL(aFrame
))
2155 aResult
->right
= left
;
2156 aResult
->left
= right
;
2160 aResult
->right
= right
;
2161 aResult
->left
= left
;
2168 nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext
* aContext
,
2170 uint8_t aOverflowRect
,
2173 /* This is disabled for now, because it causes invalidation problems --
2174 * see bug 420381. The effect of not updating the overflow area is that
2175 * for dropdown buttons in content areas, there is a 1px border on 3 sides
2176 * where, if invalidated, the dropdown control probably won't be repainted.
2177 * This is fairly minor, as by default there is nothing in that area, and
2178 * a border only shows up if the widget is being hovered.
2181 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
2182 /* We explicitly draw dropdown buttons in HTML content 1px bigger
2183 * up, right, and bottom so that they overlap the dropdown's border
2184 * like they're supposed to.
2186 if (aWidgetType
== NS_THEME_DROPDOWN_BUTTON
&&
2187 IsHTMLContent(aFrame
) &&
2188 !IsWidgetStyled(aFrame
->GetParent()->PresContext(),
2189 aFrame
->GetParent(),
2192 int32_t p2a
= aContext
->AppUnitsPerDevPixel();
2193 /* Note: no overflow on the left */
2194 nsMargin
m(p2a
, p2a
, p2a
, 0);
2195 aOverflowRect
->Inflate (m
);
2205 nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext
* aContext
, nsIFrame
* aFrame
,
2206 uint8_t aWidgetType
,
2207 nsIntSize
* aResult
, bool* aIsOverridable
)
2209 (*aResult
).width
= (*aResult
).height
= 0;
2210 *aIsOverridable
= true;
2212 HANDLE theme
= GetTheme(aWidgetType
);
2214 return ClassicGetMinimumWidgetSize(aContext
, aFrame
, aWidgetType
, aResult
, aIsOverridable
);
2216 switch (aWidgetType
) {
2217 case NS_THEME_GROUPBOX
:
2218 case NS_THEME_TEXTFIELD
:
2219 case NS_THEME_TOOLBOX
:
2220 case NS_THEME_WIN_MEDIA_TOOLBOX
:
2221 case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX
:
2222 case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX
:
2223 case NS_THEME_TOOLBAR
:
2224 case NS_THEME_STATUSBAR
:
2225 case NS_THEME_PROGRESSBAR_CHUNK
:
2226 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
2227 case NS_THEME_TAB_PANELS
:
2228 case NS_THEME_TAB_PANEL
:
2229 case NS_THEME_LISTBOX
:
2230 case NS_THEME_TREEVIEW
:
2231 case NS_THEME_MENUITEMTEXT
:
2232 case NS_THEME_WIN_GLASS
:
2233 case NS_THEME_WIN_BORDERLESS_GLASS
:
2234 return NS_OK
; // Don't worry about it.
2237 if (aWidgetType
== NS_THEME_MENUITEM
&& IsTopLevelMenu(aFrame
))
2238 return NS_OK
; // Don't worry about it for top level menus
2240 // Call GetSystemMetrics to determine size for WinXP scrollbars
2241 // (GetThemeSysSize API returns the optimal size for the theme, but
2242 // Windows appears to always use metrics when drawing standard scrollbars)
2243 THEMESIZE sizeReq
= TS_TRUE
; // Best-fit size
2244 switch (aWidgetType
) {
2245 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
2246 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
2247 case NS_THEME_SCROLLBAR_BUTTON_UP
:
2248 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
2249 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
2250 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
2251 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
2252 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
2253 case NS_THEME_DROPDOWN_BUTTON
:
2254 return ClassicGetMinimumWidgetSize(aContext
, aFrame
, aWidgetType
, aResult
, aIsOverridable
);
2256 case NS_THEME_MENUITEM
:
2257 case NS_THEME_CHECKMENUITEM
:
2258 case NS_THEME_RADIOMENUITEM
:
2259 if(!IsTopLevelMenu(aFrame
))
2261 SIZE
gutterSize(GetGutterSize(theme
, nullptr));
2262 aResult
->width
= gutterSize
.cx
;
2263 aResult
->height
= gutterSize
.cy
;
2268 case NS_THEME_MENUIMAGE
:
2269 case NS_THEME_MENUCHECKBOX
:
2270 case NS_THEME_MENURADIO
:
2272 SIZE
boxSize(GetGutterSize(theme
, nullptr));
2273 aResult
->width
= boxSize
.cx
+2;
2274 aResult
->height
= boxSize
.cy
;
2275 *aIsOverridable
= false;
2278 case NS_THEME_MENUITEMTEXT
:
2281 case NS_THEME_MENUARROW
:
2282 aResult
->width
= 26;
2283 aResult
->height
= 16;
2286 case NS_THEME_PROGRESSBAR
:
2287 case NS_THEME_PROGRESSBAR_VERTICAL
:
2288 // Best-fit size for progress meters is too large for most
2289 // themes. We want these widgets to be able to really shrink
2290 // down, so use the min-size request value (of 0).
2294 case NS_THEME_RESIZER
:
2295 *aIsOverridable
= false;
2298 case NS_THEME_RANGE_THUMB
:
2299 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
2300 case NS_THEME_SCALE_THUMB_VERTICAL
:
2302 *aIsOverridable
= false;
2303 // on Vista, GetThemePartAndState returns odd values for
2304 // scale thumbs, so use a hardcoded size instead.
2305 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
) {
2306 if (aWidgetType
== NS_THEME_SCALE_THUMB_HORIZONTAL
||
2307 (aWidgetType
== NS_THEME_RANGE_THUMB
&& IsRangeHorizontal(aFrame
))) {
2308 aResult
->width
= 12;
2309 aResult
->height
= 20;
2312 aResult
->width
= 20;
2313 aResult
->height
= 12;
2320 case NS_THEME_TOOLBAR_SEPARATOR
:
2321 // that's 2px left margin, 2px right margin and 2px separator
2322 // (the margin is drawn as part of the separator, though)
2326 case NS_THEME_BUTTON
:
2327 // We should let HTML buttons shrink to their min size.
2328 // FIXME bug 403934: We should probably really separate
2329 // GetPreferredWidgetSize from GetMinimumWidgetSize, so callers can
2330 // use the one they want.
2331 if (aFrame
->GetContent()->IsHTML()) {
2336 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
2337 case NS_THEME_WINDOW_BUTTON_RESTORE
:
2338 // The only way to get accurate titlebar button info is to query a
2339 // window w/buttons when it's visible. nsWindow takes care of this and
2340 // stores that info in nsUXThemeData.
2341 aResult
->width
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_RESTORE
].cx
;
2342 aResult
->height
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_RESTORE
].cy
;
2343 // For XP, subtract 4 from system metrics dimensions.
2344 if (WinUtils::GetWindowsVersion() == WinUtils::WINXP_VERSION
) {
2345 aResult
->width
-= 4;
2346 aResult
->height
-= 4;
2348 AddPaddingRect(aResult
, CAPTIONBUTTON_RESTORE
);
2349 *aIsOverridable
= false;
2352 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
2353 aResult
->width
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_MINIMIZE
].cx
;
2354 aResult
->height
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_MINIMIZE
].cy
;
2355 if (WinUtils::GetWindowsVersion() == WinUtils::WINXP_VERSION
) {
2356 aResult
->width
-= 4;
2357 aResult
->height
-= 4;
2359 AddPaddingRect(aResult
, CAPTIONBUTTON_MINIMIZE
);
2360 *aIsOverridable
= false;
2363 case NS_THEME_WINDOW_BUTTON_CLOSE
:
2364 aResult
->width
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_CLOSE
].cx
;
2365 aResult
->height
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_CLOSE
].cy
;
2366 if (WinUtils::GetWindowsVersion() == WinUtils::WINXP_VERSION
) {
2367 aResult
->width
-= 4;
2368 aResult
->height
-= 4;
2370 AddPaddingRect(aResult
, CAPTIONBUTTON_CLOSE
);
2371 *aIsOverridable
= false;
2374 case NS_THEME_WINDOW_TITLEBAR
:
2375 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
2376 aResult
->height
= GetSystemMetrics(SM_CYCAPTION
);
2377 aResult
->height
+= GetSystemMetrics(SM_CYFRAME
);
2378 aResult
->height
+= GetSystemMetrics(SM_CXPADDEDBORDER
);
2379 *aIsOverridable
= false;
2382 case NS_THEME_WINDOW_BUTTON_BOX
:
2383 case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
:
2384 if (nsUXThemeData::CheckForCompositor()) {
2385 aResult
->width
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_BUTTONBOX
].cx
;
2386 aResult
->height
= nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_BUTTONBOX
].cy
2387 - GetSystemMetrics(SM_CYFRAME
)
2388 - GetSystemMetrics(SM_CXPADDEDBORDER
);
2389 if (aWidgetType
== NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
) {
2390 aResult
->width
+= 1;
2391 aResult
->height
-= 2;
2393 *aIsOverridable
= false;
2398 case NS_THEME_WINDOW_FRAME_LEFT
:
2399 case NS_THEME_WINDOW_FRAME_RIGHT
:
2400 case NS_THEME_WINDOW_FRAME_BOTTOM
:
2401 aResult
->width
= GetSystemMetrics(SM_CXFRAME
);
2402 aResult
->height
= GetSystemMetrics(SM_CYFRAME
);
2403 *aIsOverridable
= false;
2407 int32_t part
, state
;
2408 nsresult rv
= GetThemePartAndState(aFrame
, aWidgetType
, part
, state
);
2412 HDC hdc
= gfxWindowsPlatform::GetPlatform()->GetScreenDC();
2414 return NS_ERROR_FAILURE
;
2417 GetThemePartSize(theme
, hdc
, part
, state
, nullptr, sizeReq
, &sz
);
2418 aResult
->width
= sz
.cx
;
2419 aResult
->height
= sz
.cy
;
2421 switch(aWidgetType
) {
2422 case NS_THEME_SPINNER_UP_BUTTON
:
2423 case NS_THEME_SPINNER_DOWN_BUTTON
:
2425 aResult
->height
= aResult
->height
/ 2 + 1;
2428 case NS_THEME_MENUSEPARATOR
:
2430 SIZE
gutterSize(GetGutterSize(theme
,hdc
));
2431 aResult
->width
+= gutterSize
.cx
;
2440 nsNativeThemeWin::WidgetStateChanged(nsIFrame
* aFrame
, uint8_t aWidgetType
,
2441 nsIAtom
* aAttribute
, bool* aShouldRepaint
)
2443 // Some widget types just never change state.
2444 if (aWidgetType
== NS_THEME_TOOLBOX
||
2445 aWidgetType
== NS_THEME_WIN_MEDIA_TOOLBOX
||
2446 aWidgetType
== NS_THEME_WIN_COMMUNICATIONS_TOOLBOX
||
2447 aWidgetType
== NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX
||
2448 aWidgetType
== NS_THEME_TOOLBAR
||
2449 aWidgetType
== NS_THEME_STATUSBAR
|| aWidgetType
== NS_THEME_STATUSBAR_PANEL
||
2450 aWidgetType
== NS_THEME_STATUSBAR_RESIZER_PANEL
||
2451 aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK
||
2452 aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
||
2453 aWidgetType
== NS_THEME_PROGRESSBAR
||
2454 aWidgetType
== NS_THEME_PROGRESSBAR_VERTICAL
||
2455 aWidgetType
== NS_THEME_TOOLTIP
||
2456 aWidgetType
== NS_THEME_TAB_PANELS
||
2457 aWidgetType
== NS_THEME_TAB_PANEL
||
2458 aWidgetType
== NS_THEME_TOOLBAR_SEPARATOR
||
2459 aWidgetType
== NS_THEME_WIN_GLASS
||
2460 aWidgetType
== NS_THEME_WIN_BORDERLESS_GLASS
) {
2461 *aShouldRepaint
= false;
2465 if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR
||
2466 aWidgetType
== NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
||
2467 aWidgetType
== NS_THEME_WINDOW_FRAME_LEFT
||
2468 aWidgetType
== NS_THEME_WINDOW_FRAME_RIGHT
||
2469 aWidgetType
== NS_THEME_WINDOW_FRAME_BOTTOM
||
2470 aWidgetType
== NS_THEME_WINDOW_BUTTON_CLOSE
||
2471 aWidgetType
== NS_THEME_WINDOW_BUTTON_MINIMIZE
||
2472 aWidgetType
== NS_THEME_WINDOW_BUTTON_MINIMIZE
||
2473 aWidgetType
== NS_THEME_WINDOW_BUTTON_RESTORE
) {
2474 *aShouldRepaint
= true;
2478 // On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
2479 if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION
&&
2480 (aWidgetType
== NS_THEME_SCROLLBAR_TRACK_VERTICAL
||
2481 aWidgetType
== NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
)) {
2482 *aShouldRepaint
= false;
2486 // We need to repaint the dropdown arrow in vista HTML combobox controls when
2487 // the control is closed to get rid of the hover effect.
2488 if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION
&&
2489 (aWidgetType
== NS_THEME_DROPDOWN
|| aWidgetType
== NS_THEME_DROPDOWN_BUTTON
) &&
2490 IsHTMLContent(aFrame
))
2492 *aShouldRepaint
= true;
2496 // XXXdwh Not sure what can really be done here. Can at least guess for
2497 // specific widgets that they're highly unlikely to have certain states.
2498 // For example, a toolbar doesn't care about any states.
2500 // Hover/focus/active changed. Always repaint.
2501 *aShouldRepaint
= true;
2504 // Check the attribute to see if it's relevant.
2505 // disabled, checked, dlgtype, default, etc.
2506 *aShouldRepaint
= false;
2507 if (aAttribute
== nsGkAtoms::disabled
||
2508 aAttribute
== nsGkAtoms::checked
||
2509 aAttribute
== nsGkAtoms::selected
||
2510 aAttribute
== nsGkAtoms::readonly
||
2511 aAttribute
== nsGkAtoms::open
||
2512 aAttribute
== nsGkAtoms::menuactive
||
2513 aAttribute
== nsGkAtoms::focused
)
2514 *aShouldRepaint
= true;
2521 nsNativeThemeWin::ThemeChanged()
2523 nsUXThemeData::Invalidate();
2528 nsNativeThemeWin::ThemeSupportsWidget(nsPresContext
* aPresContext
,
2530 uint8_t aWidgetType
)
2532 // XXXdwh We can go even further and call the API to ask if support exists for
2533 // specific widgets.
2535 if (aPresContext
&& !aPresContext
->PresShell()->IsThemeSupportEnabled())
2538 HANDLE theme
= nullptr;
2539 if (aWidgetType
== NS_THEME_CHECKBOX_CONTAINER
)
2540 theme
= GetTheme(NS_THEME_CHECKBOX
);
2541 else if (aWidgetType
== NS_THEME_RADIO_CONTAINER
)
2542 theme
= GetTheme(NS_THEME_RADIO
);
2544 theme
= GetTheme(aWidgetType
);
2546 if ((theme
) || (!theme
&& ClassicThemeSupportsWidget(aPresContext
, aFrame
, aWidgetType
)))
2547 // turn off theming for some HTML widgets styled by the page
2548 return (!IsWidgetStyled(aPresContext
, aFrame
, aWidgetType
));
2554 nsNativeThemeWin::WidgetIsContainer(uint8_t aWidgetType
)
2556 // XXXdwh At some point flesh all of this out.
2557 if (aWidgetType
== NS_THEME_DROPDOWN_BUTTON
||
2558 aWidgetType
== NS_THEME_RADIO
||
2559 aWidgetType
== NS_THEME_CHECKBOX
)
2565 nsNativeThemeWin::ThemeDrawsFocusForWidget(uint8_t aWidgetType
)
2571 nsNativeThemeWin::ThemeNeedsComboboxDropmarker()
2577 nsNativeThemeWin::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType
)
2579 switch (aWidgetType
) {
2580 case NS_THEME_WINDOW_TITLEBAR
:
2581 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
2582 case NS_THEME_WINDOW_FRAME_LEFT
:
2583 case NS_THEME_WINDOW_FRAME_RIGHT
:
2584 case NS_THEME_WINDOW_FRAME_BOTTOM
:
2585 case NS_THEME_WINDOW_BUTTON_CLOSE
:
2586 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
2587 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
2588 case NS_THEME_WINDOW_BUTTON_RESTORE
:
2595 nsITheme::Transparency
2596 nsNativeThemeWin::GetWidgetTransparency(nsIFrame
* aFrame
, uint8_t aWidgetType
)
2598 switch (aWidgetType
) {
2599 case NS_THEME_SCROLLBAR_SMALL
:
2600 case NS_THEME_SCROLLBAR
:
2601 case NS_THEME_STATUSBAR
:
2602 // Knowing that scrollbars and statusbars are opaque improves
2603 // performance, because we create layers for them. This better be
2604 // true across all Windows themes! If it's not true, we should
2605 // paint an opaque background for them to make it true!
2607 case NS_THEME_WIN_GLASS
:
2608 case NS_THEME_WIN_BORDERLESS_GLASS
:
2609 case NS_THEME_SCALE_HORIZONTAL
:
2610 case NS_THEME_SCALE_VERTICAL
:
2611 case NS_THEME_PROGRESSBAR
:
2612 case NS_THEME_PROGRESSBAR_VERTICAL
:
2613 case NS_THEME_PROGRESSBAR_CHUNK
:
2614 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
2615 case NS_THEME_RANGE
:
2616 return eTransparent
;
2619 HANDLE theme
= GetTheme(aWidgetType
);
2620 // For the classic theme we don't really have a way of knowing
2622 // menu backgrounds and tooltips which can't be themed are opaque
2623 if (aWidgetType
== NS_THEME_MENUPOPUP
|| aWidgetType
== NS_THEME_TOOLTIP
) {
2626 return eUnknownTransparency
;
2629 int32_t part
, state
;
2630 nsresult rv
= GetThemePartAndState(aFrame
, aWidgetType
, part
, state
);
2631 // Fail conservatively
2632 NS_ENSURE_SUCCESS(rv
, eUnknownTransparency
);
2635 // Not a real part code, so IsThemeBackgroundPartiallyTransparent may
2636 // not work, so don't call it.
2637 return eUnknownTransparency
;
2640 if (IsThemeBackgroundPartiallyTransparent(theme
, part
, state
))
2641 return eTransparent
;
2645 /* Windows 9x/NT/2000/Classic XP Theme Support */
2648 nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext
* aPresContext
,
2650 uint8_t aWidgetType
)
2652 switch (aWidgetType
) {
2653 case NS_THEME_RESIZER
:
2655 // The classic native resizer has an opaque grey background which doesn't
2656 // match the usually white background of the scrollable container, so
2657 // only support the native resizer if not in a scrollframe.
2658 nsIFrame
* parentFrame
= aFrame
->GetParent();
2659 return (!parentFrame
|| parentFrame
->GetType() != nsGkAtoms::scrollFrame
);
2661 case NS_THEME_MENUBAR
:
2662 case NS_THEME_MENUPOPUP
:
2663 // Classic non-flat menus are handled almost entirely through CSS.
2664 if (!nsUXThemeData::sFlatMenus
)
2666 case NS_THEME_BUTTON
:
2667 case NS_THEME_TEXTFIELD
:
2668 case NS_THEME_TEXTFIELD_MULTILINE
:
2669 case NS_THEME_CHECKBOX
:
2670 case NS_THEME_RADIO
:
2671 case NS_THEME_RANGE
:
2672 case NS_THEME_RANGE_THUMB
:
2673 case NS_THEME_GROUPBOX
:
2674 case NS_THEME_SCROLLBAR_BUTTON_UP
:
2675 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
2676 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
2677 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
2678 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
2679 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
2680 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
2681 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
2682 case NS_THEME_SCALE_HORIZONTAL
:
2683 case NS_THEME_SCALE_VERTICAL
:
2684 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
2685 case NS_THEME_SCALE_THUMB_VERTICAL
:
2686 case NS_THEME_DROPDOWN_BUTTON
:
2687 case NS_THEME_SPINNER_UP_BUTTON
:
2688 case NS_THEME_SPINNER_DOWN_BUTTON
:
2689 case NS_THEME_LISTBOX
:
2690 case NS_THEME_TREEVIEW
:
2691 case NS_THEME_DROPDOWN_TEXTFIELD
:
2692 case NS_THEME_DROPDOWN
:
2693 case NS_THEME_TOOLTIP
:
2694 case NS_THEME_STATUSBAR
:
2695 case NS_THEME_STATUSBAR_PANEL
:
2696 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
2697 case NS_THEME_PROGRESSBAR
:
2698 case NS_THEME_PROGRESSBAR_VERTICAL
:
2699 case NS_THEME_PROGRESSBAR_CHUNK
:
2700 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
2702 case NS_THEME_TAB_PANEL
:
2703 case NS_THEME_TAB_PANELS
:
2704 case NS_THEME_MENUITEM
:
2705 case NS_THEME_CHECKMENUITEM
:
2706 case NS_THEME_RADIOMENUITEM
:
2707 case NS_THEME_MENUCHECKBOX
:
2708 case NS_THEME_MENURADIO
:
2709 case NS_THEME_MENUARROW
:
2710 case NS_THEME_MENUSEPARATOR
:
2711 case NS_THEME_MENUITEMTEXT
:
2712 case NS_THEME_WINDOW_TITLEBAR
:
2713 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
2714 case NS_THEME_WINDOW_FRAME_LEFT
:
2715 case NS_THEME_WINDOW_FRAME_RIGHT
:
2716 case NS_THEME_WINDOW_FRAME_BOTTOM
:
2717 case NS_THEME_WINDOW_BUTTON_CLOSE
:
2718 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
2719 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
2720 case NS_THEME_WINDOW_BUTTON_RESTORE
:
2721 case NS_THEME_WINDOW_BUTTON_BOX
:
2722 case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED
:
2729 nsNativeThemeWin::ClassicGetWidgetBorder(nsDeviceContext
* aContext
,
2731 uint8_t aWidgetType
,
2732 nsIntMargin
* aResult
)
2734 switch (aWidgetType
) {
2735 case NS_THEME_GROUPBOX
:
2736 case NS_THEME_BUTTON
:
2737 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 2;
2739 case NS_THEME_STATUSBAR
:
2740 (*aResult
).bottom
= (*aResult
).left
= (*aResult
).right
= 0;
2743 case NS_THEME_LISTBOX
:
2744 case NS_THEME_TREEVIEW
:
2745 case NS_THEME_DROPDOWN
:
2746 case NS_THEME_DROPDOWN_TEXTFIELD
:
2748 case NS_THEME_TEXTFIELD
:
2749 case NS_THEME_TEXTFIELD_MULTILINE
:
2750 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 2;
2752 case NS_THEME_STATUSBAR_PANEL
:
2753 case NS_THEME_STATUSBAR_RESIZER_PANEL
: {
2755 (*aResult
).left
= 1;
2756 (*aResult
).bottom
= 1;
2757 (*aResult
).right
= aFrame
->GetNextSibling() ? 3 : 1;
2760 case NS_THEME_TOOLTIP
:
2761 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 1;
2763 case NS_THEME_PROGRESSBAR
:
2764 case NS_THEME_PROGRESSBAR_VERTICAL
:
2765 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 1;
2767 case NS_THEME_MENUBAR
:
2768 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 0;
2770 case NS_THEME_MENUPOPUP
:
2771 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 3;
2774 (*aResult
).top
= (*aResult
).bottom
= (*aResult
).left
= (*aResult
).right
= 0;
2781 nsNativeThemeWin::ClassicGetWidgetPadding(nsDeviceContext
* aContext
,
2783 uint8_t aWidgetType
,
2784 nsIntMargin
* aResult
)
2786 switch (aWidgetType
) {
2787 case NS_THEME_MENUITEM
:
2788 case NS_THEME_CHECKMENUITEM
:
2789 case NS_THEME_RADIOMENUITEM
: {
2790 int32_t part
, state
;
2793 if (NS_FAILED(ClassicGetThemePartAndState(aFrame
, aWidgetType
, part
, state
, focused
)))
2796 if (part
== 1) { // top-level menu
2797 if (nsUXThemeData::sFlatMenus
|| !(state
& DFCS_PUSHED
)) {
2798 (*aResult
).top
= (*aResult
).bottom
= (*aResult
).left
= (*aResult
).right
= 2;
2801 // make top-level menus look sunken when pushed in the Classic look
2802 (*aResult
).top
= (*aResult
).left
= 3;
2803 (*aResult
).bottom
= (*aResult
).right
= 1;
2808 (*aResult
).bottom
= (*aResult
).left
= (*aResult
).right
= 2;
2812 case NS_THEME_PROGRESSBAR
:
2813 case NS_THEME_PROGRESSBAR_VERTICAL
:
2814 (*aResult
).top
= (*aResult
).left
= (*aResult
).bottom
= (*aResult
).right
= 1;
2822 nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsRenderingContext
* aContext
, nsIFrame
* aFrame
,
2823 uint8_t aWidgetType
,
2824 nsIntSize
* aResult
, bool* aIsOverridable
)
2826 (*aResult
).width
= (*aResult
).height
= 0;
2827 *aIsOverridable
= true;
2828 switch (aWidgetType
) {
2829 case NS_THEME_RADIO
:
2830 case NS_THEME_CHECKBOX
:
2831 (*aResult
).width
= (*aResult
).height
= 13;
2833 case NS_THEME_MENUCHECKBOX
:
2834 case NS_THEME_MENURADIO
:
2835 case NS_THEME_MENUARROW
:
2836 (*aResult
).width
= ::GetSystemMetrics(SM_CXMENUCHECK
);
2837 (*aResult
).height
= ::GetSystemMetrics(SM_CYMENUCHECK
);
2839 case NS_THEME_SCROLLBAR_BUTTON_UP
:
2840 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
2841 (*aResult
).width
= ::GetSystemMetrics(SM_CXVSCROLL
);
2842 (*aResult
).height
= ::GetSystemMetrics(SM_CYVSCROLL
);
2843 *aIsOverridable
= false;
2845 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
2846 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
2847 (*aResult
).width
= ::GetSystemMetrics(SM_CXHSCROLL
);
2848 (*aResult
).height
= ::GetSystemMetrics(SM_CYHSCROLL
);
2849 *aIsOverridable
= false;
2851 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
2852 // XXX HACK We should be able to have a minimum height for the scrollbar
2853 // track. However, this causes problems when uncollapsing a scrollbar
2854 // inside a tree. See bug 201379 for details.
2856 // (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB) << 1;
2858 case NS_THEME_RANGE_THUMB
: {
2859 if (IsRangeHorizontal(aFrame
)) {
2860 (*aResult
).width
= 12;
2861 (*aResult
).height
= 20;
2863 (*aResult
).width
= 20;
2864 (*aResult
).height
= 12;
2866 *aIsOverridable
= false;
2869 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
2870 (*aResult
).width
= 12;
2871 (*aResult
).height
= 20;
2872 *aIsOverridable
= false;
2874 case NS_THEME_SCALE_THUMB_VERTICAL
:
2875 (*aResult
).width
= 20;
2876 (*aResult
).height
= 12;
2877 *aIsOverridable
= false;
2879 case NS_THEME_DROPDOWN_BUTTON
:
2880 (*aResult
).width
= ::GetSystemMetrics(SM_CXVSCROLL
);
2882 case NS_THEME_DROPDOWN
:
2883 case NS_THEME_BUTTON
:
2884 case NS_THEME_GROUPBOX
:
2885 case NS_THEME_LISTBOX
:
2886 case NS_THEME_TREEVIEW
:
2887 case NS_THEME_TEXTFIELD
:
2888 case NS_THEME_TEXTFIELD_MULTILINE
:
2889 case NS_THEME_DROPDOWN_TEXTFIELD
:
2890 case NS_THEME_STATUSBAR
:
2891 case NS_THEME_STATUSBAR_PANEL
:
2892 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
2893 case NS_THEME_PROGRESSBAR_CHUNK
:
2894 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
2895 case NS_THEME_TOOLTIP
:
2896 case NS_THEME_PROGRESSBAR
:
2897 case NS_THEME_PROGRESSBAR_VERTICAL
:
2899 case NS_THEME_TAB_PANEL
:
2900 case NS_THEME_TAB_PANELS
:
2901 // no minimum widget size
2903 case NS_THEME_RESIZER
: {
2904 NONCLIENTMETRICS nc
;
2905 nc
.cbSize
= sizeof(nc
);
2906 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, sizeof(nc
), &nc
, 0))
2907 (*aResult
).width
= (*aResult
).height
= abs(nc
.lfStatusFont
.lfHeight
) + 4;
2909 (*aResult
).width
= (*aResult
).height
= 15;
2910 *aIsOverridable
= false;
2912 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
2913 (*aResult
).width
= ::GetSystemMetrics(SM_CXVSCROLL
);
2914 (*aResult
).height
= ::GetSystemMetrics(SM_CYVTHUMB
);
2915 // Without theming, divide the thumb size by two in order to look more
2917 if (!GetTheme(aWidgetType
))
2918 (*aResult
).height
>>= 1;
2919 *aIsOverridable
= false;
2921 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
2922 (*aResult
).width
= ::GetSystemMetrics(SM_CXHTHUMB
);
2923 (*aResult
).height
= ::GetSystemMetrics(SM_CYHSCROLL
);
2924 // Without theming, divide the thumb size by two in order to look more
2926 if (!GetTheme(aWidgetType
))
2927 (*aResult
).width
>>= 1;
2928 *aIsOverridable
= false;
2930 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
2931 (*aResult
).width
= ::GetSystemMetrics(SM_CXHTHUMB
) << 1;
2934 case NS_THEME_MENUSEPARATOR
:
2937 aResult
->height
= 10;
2941 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
2942 case NS_THEME_WINDOW_TITLEBAR
:
2943 aResult
->height
= GetSystemMetrics(SM_CYCAPTION
);
2944 aResult
->height
+= GetSystemMetrics(SM_CYFRAME
);
2947 case NS_THEME_WINDOW_FRAME_LEFT
:
2948 case NS_THEME_WINDOW_FRAME_RIGHT
:
2949 aResult
->width
= GetSystemMetrics(SM_CXFRAME
);
2950 aResult
->height
= 0;
2953 case NS_THEME_WINDOW_FRAME_BOTTOM
:
2954 aResult
->height
= GetSystemMetrics(SM_CYFRAME
);
2958 case NS_THEME_WINDOW_BUTTON_CLOSE
:
2959 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
2960 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
2961 case NS_THEME_WINDOW_BUTTON_RESTORE
:
2962 aResult
->width
= GetSystemMetrics(SM_CXSIZE
);
2963 aResult
->height
= GetSystemMetrics(SM_CYSIZE
);
2964 // XXX I have no idea why these caption metrics are always off,
2966 aResult
->width
-= 2;
2967 aResult
->height
-= 4;
2968 if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MINIMIZE
) {
2969 AddPaddingRect(aResult
, CAPTIONBUTTON_MINIMIZE
);
2971 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MAXIMIZE
||
2972 aWidgetType
== NS_THEME_WINDOW_BUTTON_RESTORE
) {
2973 AddPaddingRect(aResult
, CAPTIONBUTTON_RESTORE
);
2975 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_CLOSE
) {
2976 AddPaddingRect(aResult
, CAPTIONBUTTON_CLOSE
);
2981 return NS_ERROR_FAILURE
;
2987 nsresult
nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame
* aFrame
, uint8_t aWidgetType
,
2988 int32_t& aPart
, int32_t& aState
, bool& aFocused
)
2991 switch (aWidgetType
) {
2992 case NS_THEME_BUTTON
: {
2993 nsEventStates contentState
;
2996 aState
= DFCS_BUTTONPUSH
;
2999 contentState
= GetContentState(aFrame
, aWidgetType
);
3000 if (IsDisabled(aFrame
, contentState
))
3001 aState
|= DFCS_INACTIVE
;
3002 else if (IsOpenButton(aFrame
))
3003 aState
|= DFCS_PUSHED
;
3004 else if (IsCheckedButton(aFrame
))
3005 aState
|= DFCS_CHECKED
;
3007 if (contentState
.HasAllStates(NS_EVENT_STATE_ACTIVE
| NS_EVENT_STATE_HOVER
)) {
3008 aState
|= DFCS_PUSHED
;
3009 const nsStyleUserInterface
*uiData
= aFrame
->StyleUserInterface();
3010 // The down state is flat if the button is focusable
3011 if (uiData
->mUserFocus
== NS_STYLE_USER_FOCUS_NORMAL
) {
3012 if (!aFrame
->GetContent()->IsHTML())
3013 aState
|= DFCS_FLAT
;
3018 if (contentState
.HasState(NS_EVENT_STATE_FOCUS
) ||
3019 (aState
== DFCS_BUTTONPUSH
&& IsDefaultButton(aFrame
))) {
3027 case NS_THEME_CHECKBOX
:
3028 case NS_THEME_RADIO
: {
3029 nsEventStates contentState
;
3034 nsIContent
* content
= aFrame
->GetContent();
3035 bool isCheckbox
= (aWidgetType
== NS_THEME_CHECKBOX
);
3036 bool isChecked
= GetCheckedOrSelected(aFrame
, !isCheckbox
);
3037 bool isIndeterminate
= isCheckbox
&& GetIndeterminate(aFrame
);
3040 // indeterminate state takes precedence over checkedness.
3041 if (isIndeterminate
) {
3042 aState
= DFCS_BUTTON3STATE
| DFCS_CHECKED
;
3044 aState
= DFCS_BUTTONCHECK
;
3047 aState
= DFCS_BUTTONRADIO
;
3050 aState
|= DFCS_CHECKED
;
3053 contentState
= GetContentState(aFrame
, aWidgetType
);
3054 if (!content
->IsXUL() &&
3055 contentState
.HasState(NS_EVENT_STATE_FOCUS
)) {
3059 if (IsDisabled(aFrame
, contentState
)) {
3060 aState
|= DFCS_INACTIVE
;
3061 } else if (contentState
.HasAllStates(NS_EVENT_STATE_ACTIVE
|
3062 NS_EVENT_STATE_HOVER
)) {
3063 aState
|= DFCS_PUSHED
;
3068 case NS_THEME_MENUITEM
:
3069 case NS_THEME_CHECKMENUITEM
:
3070 case NS_THEME_RADIOMENUITEM
: {
3071 bool isTopLevel
= false;
3072 bool isOpen
= false;
3073 bool isContainer
= false;
3074 nsMenuFrame
*menuFrame
= do_QueryFrame(aFrame
);
3075 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
3077 // We indicate top-level-ness using aPart. 0 is a normal menu item,
3078 // 1 is a top-level menu item. The state of the item is composed of
3079 // DFCS_* flags only.
3084 // If this is a real menu item, we should check if it is part of the
3085 // main menu bar or not, and if it is a container, as these affect
3087 isTopLevel
= menuFrame
->IsOnMenuBar();
3088 isOpen
= menuFrame
->IsOpen();
3089 isContainer
= menuFrame
->IsMenu();
3092 if (IsDisabled(aFrame
, eventState
))
3093 aState
|= DFCS_INACTIVE
;
3098 aState
|= DFCS_PUSHED
;
3101 if (IsMenuActive(aFrame
, aWidgetType
))
3106 case NS_THEME_MENUCHECKBOX
:
3107 case NS_THEME_MENURADIO
:
3108 case NS_THEME_MENUARROW
: {
3110 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
3112 if (IsDisabled(aFrame
, eventState
))
3113 aState
|= DFCS_INACTIVE
;
3114 if (IsMenuActive(aFrame
, aWidgetType
))
3117 if (aWidgetType
== NS_THEME_MENUCHECKBOX
|| aWidgetType
== NS_THEME_MENURADIO
) {
3118 if (IsCheckedButton(aFrame
))
3119 aState
|= DFCS_CHECKED
;
3120 } else if (IsFrameRTL(aFrame
)) {
3125 case NS_THEME_LISTBOX
:
3126 case NS_THEME_TREEVIEW
:
3127 case NS_THEME_TEXTFIELD
:
3128 case NS_THEME_TEXTFIELD_MULTILINE
:
3129 case NS_THEME_DROPDOWN
:
3130 case NS_THEME_DROPDOWN_TEXTFIELD
:
3131 case NS_THEME_RANGE
:
3132 case NS_THEME_RANGE_THUMB
:
3133 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
3134 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
3135 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
3136 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
3137 case NS_THEME_SCALE_HORIZONTAL
:
3138 case NS_THEME_SCALE_VERTICAL
:
3139 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
3140 case NS_THEME_SCALE_THUMB_VERTICAL
:
3141 case NS_THEME_STATUSBAR
:
3142 case NS_THEME_STATUSBAR_PANEL
:
3143 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
3144 case NS_THEME_PROGRESSBAR_CHUNK
:
3145 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
3146 case NS_THEME_TOOLTIP
:
3147 case NS_THEME_PROGRESSBAR
:
3148 case NS_THEME_PROGRESSBAR_VERTICAL
:
3150 case NS_THEME_TAB_PANEL
:
3151 case NS_THEME_TAB_PANELS
:
3152 case NS_THEME_MENUBAR
:
3153 case NS_THEME_MENUPOPUP
:
3154 case NS_THEME_GROUPBOX
:
3155 // these don't use DrawFrameControl
3157 case NS_THEME_DROPDOWN_BUTTON
: {
3160 aState
= DFCS_SCROLLCOMBOBOX
;
3162 nsIFrame
* parentFrame
= aFrame
->GetParent();
3163 bool isHTML
= IsHTMLContent(aFrame
);
3164 bool isMenulist
= !isHTML
&& parentFrame
->GetType() == nsGkAtoms::menuFrame
;
3165 bool isOpen
= false;
3167 // HTML select and XUL menulist dropdown buttons get state from the parent.
3168 if (isHTML
|| isMenulist
)
3169 aFrame
= parentFrame
;
3171 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
3173 if (IsDisabled(aFrame
, eventState
)) {
3174 aState
|= DFCS_INACTIVE
;
3179 nsIComboboxControlFrame
* ccf
= do_QueryFrame(aFrame
);
3180 isOpen
= (ccf
&& ccf
->IsDroppedDown());
3183 isOpen
= IsOpenButton(aFrame
);
3185 // XXX Button should look active until the mouse is released, but
3186 // without making it look active when the popup is clicked.
3187 if (isOpen
&& (isHTML
|| isMenulist
))
3190 // Dropdown button active state doesn't need :hover.
3191 if (eventState
.HasState(NS_EVENT_STATE_ACTIVE
))
3192 aState
|= DFCS_PUSHED
| DFCS_FLAT
;
3196 case NS_THEME_SCROLLBAR_BUTTON_UP
:
3197 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
3198 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
3199 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
: {
3200 nsEventStates contentState
= GetContentState(aFrame
, aWidgetType
);
3203 switch (aWidgetType
) {
3204 case NS_THEME_SCROLLBAR_BUTTON_UP
:
3205 aState
= DFCS_SCROLLUP
;
3207 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
3208 aState
= DFCS_SCROLLDOWN
;
3210 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
3211 aState
= DFCS_SCROLLLEFT
;
3213 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
3214 aState
= DFCS_SCROLLRIGHT
;
3218 if (IsDisabled(aFrame
, contentState
))
3219 aState
|= DFCS_INACTIVE
;
3221 if (contentState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
3222 aState
|= DFCS_PUSHED
| DFCS_FLAT
;
3227 case NS_THEME_SPINNER_UP_BUTTON
:
3228 case NS_THEME_SPINNER_DOWN_BUTTON
: {
3229 nsEventStates contentState
= GetContentState(aFrame
, aWidgetType
);
3232 switch (aWidgetType
) {
3233 case NS_THEME_SPINNER_UP_BUTTON
:
3234 aState
= DFCS_SCROLLUP
;
3236 case NS_THEME_SPINNER_DOWN_BUTTON
:
3237 aState
= DFCS_SCROLLDOWN
;
3241 if (IsDisabled(aFrame
, contentState
))
3242 aState
|= DFCS_INACTIVE
;
3244 if (contentState
.HasAllStates(NS_EVENT_STATE_HOVER
| NS_EVENT_STATE_ACTIVE
))
3245 aState
|= DFCS_PUSHED
;
3250 case NS_THEME_RESIZER
:
3252 aState
= (IsFrameRTL(aFrame
)) ?
3253 DFCS_SCROLLSIZEGRIPRIGHT
: DFCS_SCROLLSIZEGRIP
;
3255 case NS_THEME_MENUSEPARATOR
:
3259 case NS_THEME_WINDOW_TITLEBAR
:
3260 aPart
= mozilla::widget::themeconst::WP_CAPTION
;
3261 aState
= GetTopLevelWindowActiveState(aFrame
);
3263 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
3264 aPart
= mozilla::widget::themeconst::WP_MAXCAPTION
;
3265 aState
= GetTopLevelWindowActiveState(aFrame
);
3267 case NS_THEME_WINDOW_FRAME_LEFT
:
3268 aPart
= mozilla::widget::themeconst::WP_FRAMELEFT
;
3269 aState
= GetTopLevelWindowActiveState(aFrame
);
3271 case NS_THEME_WINDOW_FRAME_RIGHT
:
3272 aPart
= mozilla::widget::themeconst::WP_FRAMERIGHT
;
3273 aState
= GetTopLevelWindowActiveState(aFrame
);
3275 case NS_THEME_WINDOW_FRAME_BOTTOM
:
3276 aPart
= mozilla::widget::themeconst::WP_FRAMEBOTTOM
;
3277 aState
= GetTopLevelWindowActiveState(aFrame
);
3279 case NS_THEME_WINDOW_BUTTON_CLOSE
:
3280 aPart
= DFC_CAPTION
;
3281 aState
= DFCS_CAPTIONCLOSE
|
3282 GetClassicWindowFrameButtonState(GetContentState(aFrame
,
3285 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
3286 aPart
= DFC_CAPTION
;
3287 aState
= DFCS_CAPTIONMIN
|
3288 GetClassicWindowFrameButtonState(GetContentState(aFrame
,
3291 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
3292 aPart
= DFC_CAPTION
;
3293 aState
= DFCS_CAPTIONMAX
|
3294 GetClassicWindowFrameButtonState(GetContentState(aFrame
,
3297 case NS_THEME_WINDOW_BUTTON_RESTORE
:
3298 aPart
= DFC_CAPTION
;
3299 aState
= DFCS_CAPTIONRESTORE
|
3300 GetClassicWindowFrameButtonState(GetContentState(aFrame
,
3304 return NS_ERROR_FAILURE
;
3307 // Draw classic Windows tab
3308 // (no system API for this, but DrawEdge can draw all the parts of a tab)
3309 static void DrawTab(HDC hdc
, const RECT
& R
, int32_t aPosition
, bool aSelected
,
3310 bool aDrawLeft
, bool aDrawRight
)
3312 int32_t leftFlag
, topFlag
, rightFlag
, lightFlag
, shadeFlag
;
3313 RECT topRect
, sideRect
, bottomRect
, lightRect
, shadeRect
;
3314 int32_t selectedOffset
, lOffset
, rOffset
;
3316 selectedOffset
= aSelected
? 1 : 0;
3317 lOffset
= aDrawLeft
? 2 : 0;
3318 rOffset
= aDrawRight
? 2 : 0;
3320 // Get info for tab orientation/position (Left, Top, Right, Bottom)
3321 switch (aPosition
) {
3323 leftFlag
= BF_TOP
; topFlag
= BF_LEFT
;
3324 rightFlag
= BF_BOTTOM
;
3325 lightFlag
= BF_DIAGONAL_ENDTOPRIGHT
;
3326 shadeFlag
= BF_DIAGONAL_ENDBOTTOMRIGHT
;
3328 ::SetRect(&topRect
, R
.left
, R
.top
+lOffset
, R
.right
, R
.bottom
-rOffset
);
3329 ::SetRect(&sideRect
, R
.left
+2, R
.top
, R
.right
-2+selectedOffset
, R
.bottom
);
3330 ::SetRect(&bottomRect
, R
.right
-2, R
.top
, R
.right
, R
.bottom
);
3331 ::SetRect(&lightRect
, R
.left
, R
.top
, R
.left
+3, R
.top
+3);
3332 ::SetRect(&shadeRect
, R
.left
+1, R
.bottom
-2, R
.left
+2, R
.bottom
-1);
3335 leftFlag
= BF_LEFT
; topFlag
= BF_TOP
;
3336 rightFlag
= BF_RIGHT
;
3337 lightFlag
= BF_DIAGONAL_ENDTOPRIGHT
;
3338 shadeFlag
= BF_DIAGONAL_ENDBOTTOMRIGHT
;
3340 ::SetRect(&topRect
, R
.left
+lOffset
, R
.top
, R
.right
-rOffset
, R
.bottom
);
3341 ::SetRect(&sideRect
, R
.left
, R
.top
+2, R
.right
, R
.bottom
-1+selectedOffset
);
3342 ::SetRect(&bottomRect
, R
.left
, R
.bottom
-1, R
.right
, R
.bottom
);
3343 ::SetRect(&lightRect
, R
.left
, R
.top
, R
.left
+3, R
.top
+3);
3344 ::SetRect(&shadeRect
, R
.right
-2, R
.top
+1, R
.right
-1, R
.top
+2);
3347 leftFlag
= BF_TOP
; topFlag
= BF_RIGHT
;
3348 rightFlag
= BF_BOTTOM
;
3349 lightFlag
= BF_DIAGONAL_ENDTOPLEFT
;
3350 shadeFlag
= BF_DIAGONAL_ENDBOTTOMLEFT
;
3352 ::SetRect(&topRect
, R
.left
, R
.top
+lOffset
, R
.right
, R
.bottom
-rOffset
);
3353 ::SetRect(&sideRect
, R
.left
+2-selectedOffset
, R
.top
, R
.right
-2, R
.bottom
);
3354 ::SetRect(&bottomRect
, R
.left
, R
.top
, R
.left
+2, R
.bottom
);
3355 ::SetRect(&lightRect
, R
.right
-3, R
.top
, R
.right
-1, R
.top
+2);
3356 ::SetRect(&shadeRect
, R
.right
-2, R
.bottom
-3, R
.right
, R
.bottom
-1);
3359 leftFlag
= BF_LEFT
; topFlag
= BF_BOTTOM
;
3360 rightFlag
= BF_RIGHT
;
3361 lightFlag
= BF_DIAGONAL_ENDTOPLEFT
;
3362 shadeFlag
= BF_DIAGONAL_ENDBOTTOMLEFT
;
3364 ::SetRect(&topRect
, R
.left
+lOffset
, R
.top
, R
.right
-rOffset
, R
.bottom
);
3365 ::SetRect(&sideRect
, R
.left
, R
.top
+2-selectedOffset
, R
.right
, R
.bottom
-2);
3366 ::SetRect(&bottomRect
, R
.left
, R
.top
, R
.right
, R
.top
+2);
3367 ::SetRect(&lightRect
, R
.left
, R
.bottom
-3, R
.left
+2, R
.bottom
-1);
3368 ::SetRect(&shadeRect
, R
.right
-2, R
.bottom
-3, R
.right
, R
.bottom
-1);
3373 ::FillRect(hdc
, &R
, (HBRUSH
) (COLOR_3DFACE
+1) );
3376 ::DrawEdge(hdc
, &topRect
, EDGE_RAISED
, BF_SOFT
| topFlag
);
3380 ::DrawEdge(hdc
, &bottomRect
, EDGE_RAISED
, BF_SOFT
| topFlag
);
3387 ::DrawEdge(hdc
, &sideRect
, EDGE_RAISED
, BF_SOFT
| leftFlag
| rightFlag
);
3389 // Tab Diagonal Corners
3391 ::DrawEdge(hdc
, &lightRect
, EDGE_RAISED
, BF_SOFT
| lightFlag
);
3394 ::DrawEdge(hdc
, &shadeRect
, EDGE_RAISED
, BF_SOFT
| shadeFlag
);
3397 static void DrawMenuImage(HDC hdc
, const RECT
& rc
, int32_t aComponent
, uint32_t aColor
)
3399 // This procedure creates a memory bitmap to contain the check mark, draws
3400 // it into the bitmap (it is a mask image), then composes it onto the menu
3401 // item in appropriate colors.
3402 HDC hMemoryDC
= ::CreateCompatibleDC(hdc
);
3404 // XXXjgr We should ideally be caching these, but we wont be notified when
3405 // they change currently, so we can't do so easily. Same for the bitmap.
3406 int checkW
= ::GetSystemMetrics(SM_CXMENUCHECK
);
3407 int checkH
= ::GetSystemMetrics(SM_CYMENUCHECK
);
3409 HBITMAP hMonoBitmap
= ::CreateBitmap(checkW
, checkH
, 1, 1, nullptr);
3412 HBITMAP hPrevBitmap
= (HBITMAP
) ::SelectObject(hMemoryDC
, hMonoBitmap
);
3415 // XXXjgr This will go pear-shaped if the image is bigger than the
3416 // provided rect. What should we do?
3417 RECT imgRect
= { 0, 0, checkW
, checkH
};
3419 rc
.left
+ (rc
.right
- rc
.left
- checkW
) / 2,
3420 rc
.top
+ (rc
.bottom
- rc
.top
- checkH
) / 2
3423 // XXXzeniko Windows renders these 1px lower than you'd expect
3424 if (aComponent
== DFCS_MENUCHECK
|| aComponent
== DFCS_MENUBULLET
)
3427 ::DrawFrameControl(hMemoryDC
, &imgRect
, DFC_MENU
, aComponent
);
3428 COLORREF oldTextCol
= ::SetTextColor(hdc
, 0x00000000);
3429 COLORREF oldBackCol
= ::SetBkColor(hdc
, 0x00FFFFFF);
3430 ::BitBlt(hdc
, imgPos
.x
, imgPos
.y
, checkW
, checkH
, hMemoryDC
, 0, 0, SRCAND
);
3431 ::SetTextColor(hdc
, ::GetSysColor(aColor
));
3432 ::SetBkColor(hdc
, 0x00000000);
3433 ::BitBlt(hdc
, imgPos
.x
, imgPos
.y
, checkW
, checkH
, hMemoryDC
, 0, 0, SRCPAINT
);
3434 ::SetTextColor(hdc
, oldTextCol
);
3435 ::SetBkColor(hdc
, oldBackCol
);
3436 ::SelectObject(hMemoryDC
, hPrevBitmap
);
3438 ::DeleteObject(hMonoBitmap
);
3440 ::DeleteDC(hMemoryDC
);
3444 void nsNativeThemeWin::DrawCheckedRect(HDC hdc
, const RECT
& rc
, int32_t fore
, int32_t back
,
3447 static WORD patBits
[8] = {
3448 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
3451 HBITMAP patBmp
= ::CreateBitmap(8, 8, 1, 1, patBits
);
3453 HBRUSH brush
= (HBRUSH
) ::CreatePatternBrush(patBmp
);
3455 COLORREF oldForeColor
= ::SetTextColor(hdc
, ::GetSysColor(fore
));
3456 COLORREF oldBackColor
= ::SetBkColor(hdc
, ::GetSysColor(back
));
3459 ::UnrealizeObject(brush
);
3460 ::GetViewportOrgEx(hdc
, &vpOrg
);
3461 ::SetBrushOrgEx(hdc
, vpOrg
.x
+ rc
.left
, vpOrg
.y
+ rc
.top
, nullptr);
3462 HBRUSH oldBrush
= (HBRUSH
) ::SelectObject(hdc
, brush
);
3463 ::FillRect(hdc
, &rc
, brush
);
3464 ::SetTextColor(hdc
, oldForeColor
);
3465 ::SetBkColor(hdc
, oldBackColor
);
3466 ::SelectObject(hdc
, oldBrush
);
3467 ::DeleteObject(brush
);
3470 ::FillRect(hdc
, &rc
, defaultBack
);
3472 ::DeleteObject(patBmp
);
3476 nsresult
nsNativeThemeWin::ClassicDrawWidgetBackground(nsRenderingContext
* aContext
,
3478 uint8_t aWidgetType
,
3479 const nsRect
& aRect
,
3480 const nsRect
& aDirtyRect
)
3482 int32_t part
, state
;
3485 rv
= ClassicGetThemePartAndState(aFrame
, aWidgetType
, part
, state
, focused
);
3489 if (AssumeThemePartAndStateAreTransparent(part
, state
)) {
3493 gfxFloat p2a
= gfxFloat(aContext
->AppUnitsPerDevPixel());
3495 gfxRect
tr(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
),
3496 dr(aDirtyRect
.x
, aDirtyRect
.y
, aDirtyRect
.width
, aDirtyRect
.height
);
3498 tr
.ScaleInverse(p2a
);
3499 dr
.ScaleInverse(p2a
);
3501 nsRefPtr
<gfxContext
> ctx
= aContext
->ThebesContext();
3503 gfxWindowsNativeDrawing
nativeDrawing(ctx
, dr
, GetWidgetNativeDrawingFlags(aWidgetType
));
3507 HDC hdc
= nativeDrawing
.BeginNativeDrawing();
3509 return NS_ERROR_FAILURE
;
3511 nativeDrawing
.TransformToNativeRect(tr
, widgetRect
);
3514 switch (aWidgetType
) {
3516 case NS_THEME_BUTTON
: {
3518 // draw dark button focus border first
3520 brush
= ::GetSysColorBrush(COLOR_3DDKSHADOW
);
3522 ::FrameRect(hdc
, &widgetRect
, brush
);
3523 InflateRect(&widgetRect
, -1, -1);
3527 // Draw controls supported by DrawFrameControl
3528 case NS_THEME_CHECKBOX
:
3529 case NS_THEME_RADIO
:
3530 case NS_THEME_SCROLLBAR_BUTTON_UP
:
3531 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
3532 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
3533 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
3534 case NS_THEME_SPINNER_UP_BUTTON
:
3535 case NS_THEME_SPINNER_DOWN_BUTTON
:
3536 case NS_THEME_DROPDOWN_BUTTON
:
3537 case NS_THEME_RESIZER
: {
3539 // setup DC to make DrawFrameControl draw correctly
3540 oldTA
= ::SetTextAlign(hdc
, TA_TOP
| TA_LEFT
| TA_NOUPDATECP
);
3541 ::DrawFrameControl(hdc
, &widgetRect
, part
, state
);
3542 ::SetTextAlign(hdc
, oldTA
);
3544 // Draw focus rectangles for HTML checkboxes and radio buttons
3545 // XXX it'd be nice to draw these outside of the frame
3546 if (focused
&& (aWidgetType
== NS_THEME_CHECKBOX
|| aWidgetType
== NS_THEME_RADIO
)) {
3547 // setup DC to make DrawFocusRect draw correctly
3549 ::GetViewportOrgEx(hdc
, &vpOrg
);
3550 ::SetBrushOrgEx(hdc
, vpOrg
.x
+ widgetRect
.left
, vpOrg
.y
+ widgetRect
.top
, nullptr);
3552 oldColor
= ::SetTextColor(hdc
, 0);
3553 // draw focus rectangle
3554 ::DrawFocusRect(hdc
, &widgetRect
);
3555 ::SetTextColor(hdc
, oldColor
);
3559 // Draw controls with 2px 3D inset border
3560 case NS_THEME_TEXTFIELD
:
3561 case NS_THEME_TEXTFIELD_MULTILINE
:
3562 case NS_THEME_LISTBOX
:
3563 case NS_THEME_DROPDOWN
:
3564 case NS_THEME_DROPDOWN_TEXTFIELD
: {
3566 ::DrawEdge(hdc
, &widgetRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
3567 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
3569 // Fill in background
3570 if (IsDisabled(aFrame
, eventState
) ||
3571 (aFrame
->GetContent()->IsXUL() &&
3572 IsReadOnly(aFrame
)))
3573 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_BTNFACE
+1));
3575 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_WINDOW
+1));
3579 case NS_THEME_TREEVIEW
: {
3581 ::DrawEdge(hdc
, &widgetRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
3583 // Fill in window color background
3584 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_WINDOW
+1));
3588 // Draw ToolTip background
3589 case NS_THEME_TOOLTIP
:
3590 ::FrameRect(hdc
, &widgetRect
, ::GetSysColorBrush(COLOR_WINDOWFRAME
));
3591 InflateRect(&widgetRect
, -1, -1);
3592 ::FillRect(hdc
, &widgetRect
, ::GetSysColorBrush(COLOR_INFOBK
));
3595 case NS_THEME_GROUPBOX
:
3596 ::DrawEdge(hdc
, &widgetRect
, EDGE_ETCHED
, BF_RECT
| BF_ADJUST
);
3597 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_BTNFACE
+1));
3599 // Draw 3D face background controls
3600 case NS_THEME_PROGRESSBAR
:
3601 case NS_THEME_PROGRESSBAR_VERTICAL
:
3603 ::DrawEdge(hdc
, &widgetRect
, BDR_SUNKENOUTER
, BF_RECT
| BF_MIDDLE
);
3604 InflateRect(&widgetRect
, -1, -1);
3606 case NS_THEME_TAB_PANEL
:
3607 case NS_THEME_STATUSBAR
:
3608 case NS_THEME_STATUSBAR_RESIZER_PANEL
: {
3609 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_BTNFACE
+1));
3613 // Draw 3D inset statusbar panel
3614 case NS_THEME_STATUSBAR_PANEL
: {
3615 if (aFrame
->GetNextSibling())
3616 widgetRect
.right
-= 2; // space between sibling status panels
3618 ::DrawEdge(hdc
, &widgetRect
, BDR_SUNKENOUTER
, BF_RECT
| BF_MIDDLE
);
3622 // Draw scrollbar thumb
3623 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
3624 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
3625 ::DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
3628 case NS_THEME_RANGE_THUMB
:
3629 case NS_THEME_SCALE_THUMB_VERTICAL
:
3630 case NS_THEME_SCALE_THUMB_HORIZONTAL
: {
3631 nsEventStates eventState
= GetContentState(aFrame
, aWidgetType
);
3633 ::DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
3634 if (IsDisabled(aFrame
, eventState
)) {
3635 DrawCheckedRect(hdc
, widgetRect
, COLOR_3DFACE
, COLOR_3DHILIGHT
,
3636 (HBRUSH
) COLOR_3DHILIGHT
);
3641 // Draw scrollbar track background
3642 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
3643 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
: {
3645 // Windows fills in the scrollbar track differently
3646 // depending on whether these are equal
3647 DWORD color3D
, colorScrollbar
, colorWindow
;
3649 color3D
= ::GetSysColor(COLOR_3DFACE
);
3650 colorWindow
= ::GetSysColor(COLOR_WINDOW
);
3651 colorScrollbar
= ::GetSysColor(COLOR_SCROLLBAR
);
3653 if ((color3D
!= colorScrollbar
) && (colorWindow
!= colorScrollbar
))
3655 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_SCROLLBAR
+1));
3658 DrawCheckedRect(hdc
, widgetRect
, COLOR_3DHILIGHT
, COLOR_3DFACE
,
3659 (HBRUSH
) COLOR_SCROLLBAR
+1);
3661 // XXX should invert the part of the track being clicked here
3662 // but the track is never :active
3666 // Draw scale track background
3667 case NS_THEME_RANGE
:
3668 case NS_THEME_SCALE_VERTICAL
:
3669 case NS_THEME_SCALE_HORIZONTAL
: {
3670 const int32_t trackWidth
= 4;
3671 // When rounding is necessary, we round the position of the track
3672 // away from the chevron of the thumb to make it look better.
3673 if (aWidgetType
== NS_THEME_SCALE_HORIZONTAL
||
3674 (aWidgetType
== NS_THEME_RANGE
&& IsRangeHorizontal(aFrame
))) {
3675 widgetRect
.top
+= (widgetRect
.bottom
- widgetRect
.top
- trackWidth
) / 2;
3676 widgetRect
.bottom
= widgetRect
.top
+ trackWidth
;
3679 if (!IsFrameRTL(aFrame
)) {
3680 widgetRect
.left
+= (widgetRect
.right
- widgetRect
.left
- trackWidth
) / 2;
3681 widgetRect
.right
= widgetRect
.left
+ trackWidth
;
3683 widgetRect
.right
-= (widgetRect
.right
- widgetRect
.left
- trackWidth
) / 2;
3684 widgetRect
.left
= widgetRect
.right
- trackWidth
;
3688 ::DrawEdge(hdc
, &widgetRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
3689 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) GetStockObject(GRAY_BRUSH
));
3693 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
3694 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_HIGHLIGHT
+1));
3697 case NS_THEME_PROGRESSBAR_CHUNK
: {
3698 nsIFrame
* stateFrame
= aFrame
->GetParent();
3699 nsEventStates eventStates
= GetContentState(stateFrame
, aWidgetType
);
3701 bool indeterminate
= IsIndeterminateProgress(stateFrame
, eventStates
);
3702 bool vertical
= IsVerticalProgress(stateFrame
) ||
3703 aWidgetType
== NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
;
3704 int32_t overlayPart
= GetProgressOverlayStyle(vertical
);
3706 nsIContent
* content
= aFrame
->GetContent();
3707 if (!indeterminate
|| !content
) {
3708 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_HIGHLIGHT
+1));
3713 CalculateProgressOverlayRect(aFrame
, &widgetRect
, vertical
,
3714 indeterminate
, true);
3716 ::FillRect(hdc
, &overlayRect
, (HBRUSH
) (COLOR_HIGHLIGHT
+1));
3718 if (!QueueAnimatedContentForRefresh(aFrame
->GetContent(), 30)) {
3719 NS_WARNING("unable to animate progress widget!");
3725 case NS_THEME_TAB
: {
3726 DrawTab(hdc
, widgetRect
,
3727 IsBottomTab(aFrame
) ? BF_BOTTOM
: BF_TOP
,
3728 IsSelectedTab(aFrame
),
3729 !IsRightToSelectedTab(aFrame
),
3730 !IsLeftToSelectedTab(aFrame
));
3734 case NS_THEME_TAB_PANELS
:
3735 ::DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_SOFT
| BF_MIDDLE
|
3736 BF_LEFT
| BF_RIGHT
| BF_BOTTOM
);
3739 case NS_THEME_MENUBAR
:
3741 case NS_THEME_MENUPOPUP
:
3742 NS_ASSERTION(nsUXThemeData::sFlatMenus
, "Classic menus are styled entirely through CSS");
3743 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_MENU
+1));
3744 ::FrameRect(hdc
, &widgetRect
, ::GetSysColorBrush(COLOR_BTNSHADOW
));
3746 case NS_THEME_MENUITEM
:
3747 case NS_THEME_CHECKMENUITEM
:
3748 case NS_THEME_RADIOMENUITEM
:
3749 // part == 0 for normal items
3750 // part == 1 for top-level menu items
3751 if (nsUXThemeData::sFlatMenus
) {
3752 // Not disabled and hot/pushed.
3753 if ((state
& (DFCS_HOT
| DFCS_PUSHED
)) != 0) {
3754 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_MENUHILIGHT
+1));
3755 ::FrameRect(hdc
, &widgetRect
, ::GetSysColorBrush(COLOR_HIGHLIGHT
));
3759 if ((state
& DFCS_INACTIVE
) == 0) {
3760 if ((state
& DFCS_PUSHED
) != 0) {
3761 ::DrawEdge(hdc
, &widgetRect
, BDR_SUNKENOUTER
, BF_RECT
);
3762 } else if ((state
& DFCS_HOT
) != 0) {
3763 ::DrawEdge(hdc
, &widgetRect
, BDR_RAISEDINNER
, BF_RECT
);
3767 if ((state
& (DFCS_HOT
| DFCS_PUSHED
)) != 0) {
3768 ::FillRect(hdc
, &widgetRect
, (HBRUSH
) (COLOR_HIGHLIGHT
+1));
3773 case NS_THEME_MENUCHECKBOX
:
3774 case NS_THEME_MENURADIO
:
3775 if (!(state
& DFCS_CHECKED
))
3776 break; // nothin' to do
3777 case NS_THEME_MENUARROW
: {
3778 uint32_t color
= COLOR_MENUTEXT
;
3779 if ((state
& DFCS_INACTIVE
))
3780 color
= COLOR_GRAYTEXT
;
3781 else if ((state
& DFCS_HOT
))
3782 color
= COLOR_HIGHLIGHTTEXT
;
3784 if (aWidgetType
== NS_THEME_MENUCHECKBOX
)
3785 DrawMenuImage(hdc
, widgetRect
, DFCS_MENUCHECK
, color
);
3786 else if (aWidgetType
== NS_THEME_MENURADIO
)
3787 DrawMenuImage(hdc
, widgetRect
, DFCS_MENUBULLET
, color
);
3788 else if (aWidgetType
== NS_THEME_MENUARROW
)
3789 DrawMenuImage(hdc
, widgetRect
,
3790 (state
& DFCS_RTL
) ? DFCS_MENUARROWRIGHT
: DFCS_MENUARROW
,
3794 case NS_THEME_MENUSEPARATOR
: {
3795 // separators are offset by a bit (see menu.css)
3799 // This magic number is brought to you by the value in menu.css
3800 widgetRect
.top
+= 4;
3801 // Our rectangles are 1 pixel high (see border size in menu.css)
3802 widgetRect
.bottom
= widgetRect
.top
+1;
3803 ::FillRect(hdc
, &widgetRect
, (HBRUSH
)(COLOR_3DSHADOW
+1));
3805 widgetRect
.bottom
++;
3806 ::FillRect(hdc
, &widgetRect
, (HBRUSH
)(COLOR_3DHILIGHT
+1));
3810 case NS_THEME_WINDOW_TITLEBAR
:
3811 case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED
:
3813 RECT rect
= widgetRect
;
3814 int32_t offset
= GetSystemMetrics(SM_CXFRAME
);
3817 // first fill the area to the color of the window background
3818 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_3DFACE
+1));
3820 // inset the caption area so it doesn't overflow.
3822 // if enabled, draw a gradient titlebar background, otherwise
3823 // fill with a solid color.
3825 SystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &bFlag
, 0);
3827 if (state
== mozilla::widget::themeconst::FS_ACTIVE
)
3828 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_ACTIVECAPTION
+1));
3830 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_INACTIVECAPTION
+1));
3832 DWORD startColor
, endColor
;
3833 if (state
== mozilla::widget::themeconst::FS_ACTIVE
) {
3834 startColor
= GetSysColor(COLOR_ACTIVECAPTION
);
3835 endColor
= GetSysColor(COLOR_GRADIENTACTIVECAPTION
);
3837 startColor
= GetSysColor(COLOR_INACTIVECAPTION
);
3838 endColor
= GetSysColor(COLOR_GRADIENTINACTIVECAPTION
);
3841 TRIVERTEX vertex
[2];
3842 vertex
[0].x
= rect
.left
;
3843 vertex
[0].y
= rect
.top
;
3844 vertex
[0].Red
= GetRValue(startColor
) << 8;
3845 vertex
[0].Green
= GetGValue(startColor
) << 8;
3846 vertex
[0].Blue
= GetBValue(startColor
) << 8;
3847 vertex
[0].Alpha
= 0;
3849 vertex
[1].x
= rect
.right
;
3850 vertex
[1].y
= rect
.bottom
;
3851 vertex
[1].Red
= GetRValue(endColor
) << 8;
3852 vertex
[1].Green
= GetGValue(endColor
) << 8;
3853 vertex
[1].Blue
= GetBValue(endColor
) << 8;
3854 vertex
[1].Alpha
= 0;
3856 GRADIENT_RECT gRect
;
3857 gRect
.UpperLeft
= 0;
3858 gRect
.LowerRight
= 1;
3859 // available on win2k & up
3860 GradientFill(hdc
, vertex
, 2, &gRect
, 1, GRADIENT_FILL_RECT_H
);
3863 if (aWidgetType
== NS_THEME_WINDOW_TITLEBAR
) {
3864 // frame things up with a top raised border.
3865 DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_TOP
);
3870 case NS_THEME_WINDOW_FRAME_LEFT
:
3871 DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_LEFT
);
3874 case NS_THEME_WINDOW_FRAME_RIGHT
:
3875 DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_RIGHT
);
3878 case NS_THEME_WINDOW_FRAME_BOTTOM
:
3879 DrawEdge(hdc
, &widgetRect
, EDGE_RAISED
, BF_BOTTOM
);
3882 case NS_THEME_WINDOW_BUTTON_CLOSE
:
3883 case NS_THEME_WINDOW_BUTTON_MINIMIZE
:
3884 case NS_THEME_WINDOW_BUTTON_MAXIMIZE
:
3885 case NS_THEME_WINDOW_BUTTON_RESTORE
:
3887 if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MINIMIZE
) {
3888 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_MINIMIZE
);
3890 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_MAXIMIZE
||
3891 aWidgetType
== NS_THEME_WINDOW_BUTTON_RESTORE
) {
3892 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_RESTORE
);
3894 else if (aWidgetType
== NS_THEME_WINDOW_BUTTON_CLOSE
) {
3895 OffsetBackgroundRect(widgetRect
, CAPTIONBUTTON_CLOSE
);
3897 int32_t oldTA
= SetTextAlign(hdc
, TA_TOP
| TA_LEFT
| TA_NOUPDATECP
);
3898 DrawFrameControl(hdc
, &widgetRect
, part
, state
);
3899 SetTextAlign(hdc
, oldTA
);
3904 rv
= NS_ERROR_FAILURE
;
3908 nativeDrawing
.EndNativeDrawing();
3913 if (nativeDrawing
.ShouldRenderAgain())
3916 nativeDrawing
.PaintToContext();
3922 nsNativeThemeWin::GetWidgetNativeDrawingFlags(uint8_t aWidgetType
)
3924 switch (aWidgetType
) {
3925 case NS_THEME_BUTTON
:
3926 case NS_THEME_TEXTFIELD
:
3927 case NS_THEME_TEXTFIELD_MULTILINE
:
3929 case NS_THEME_DROPDOWN
:
3930 case NS_THEME_DROPDOWN_TEXTFIELD
:
3932 gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA
|
3933 gfxWindowsNativeDrawing::CAN_AXIS_ALIGNED_SCALE
|
3934 gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM
;
3936 // need to check these others
3937 case NS_THEME_RANGE
:
3938 case NS_THEME_RANGE_THUMB
:
3939 case NS_THEME_SCROLLBAR_BUTTON_UP
:
3940 case NS_THEME_SCROLLBAR_BUTTON_DOWN
:
3941 case NS_THEME_SCROLLBAR_BUTTON_LEFT
:
3942 case NS_THEME_SCROLLBAR_BUTTON_RIGHT
:
3943 case NS_THEME_SCROLLBAR_THUMB_VERTICAL
:
3944 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL
:
3945 case NS_THEME_SCROLLBAR_TRACK_VERTICAL
:
3946 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL
:
3947 case NS_THEME_SCALE_HORIZONTAL
:
3948 case NS_THEME_SCALE_VERTICAL
:
3949 case NS_THEME_SCALE_THUMB_HORIZONTAL
:
3950 case NS_THEME_SCALE_THUMB_VERTICAL
:
3951 case NS_THEME_SPINNER_UP_BUTTON
:
3952 case NS_THEME_SPINNER_DOWN_BUTTON
:
3953 case NS_THEME_LISTBOX
:
3954 case NS_THEME_TREEVIEW
:
3955 case NS_THEME_TOOLTIP
:
3956 case NS_THEME_STATUSBAR
:
3957 case NS_THEME_STATUSBAR_PANEL
:
3958 case NS_THEME_STATUSBAR_RESIZER_PANEL
:
3959 case NS_THEME_RESIZER
:
3960 case NS_THEME_PROGRESSBAR
:
3961 case NS_THEME_PROGRESSBAR_VERTICAL
:
3962 case NS_THEME_PROGRESSBAR_CHUNK
:
3963 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL
:
3965 case NS_THEME_TAB_PANEL
:
3966 case NS_THEME_TAB_PANELS
:
3967 case NS_THEME_MENUBAR
:
3968 case NS_THEME_MENUPOPUP
:
3969 case NS_THEME_MENUITEM
:
3972 // the dropdown button /almost/ renders correctly with scaling,
3973 // except that the graphic in the dropdown button (the downward arrow)
3974 // doesn't get scaled up.
3975 case NS_THEME_DROPDOWN_BUTTON
:
3976 // these are definitely no; they're all graphics that don't get scaled up
3977 case NS_THEME_CHECKBOX
:
3978 case NS_THEME_RADIO
:
3979 case NS_THEME_GROUPBOX
:
3980 case NS_THEME_CHECKMENUITEM
:
3981 case NS_THEME_RADIOMENUITEM
:
3982 case NS_THEME_MENUCHECKBOX
:
3983 case NS_THEME_MENURADIO
:
3984 case NS_THEME_MENUARROW
:
3986 gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA
|
3987 gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE
|
3988 gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM
;
3992 gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA
|
3993 gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE
|
3994 gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM
;
3997 ///////////////////////////////////////////
3999 ///////////////////////////////////////////
4001 // from nsWindow.cpp
4002 extern bool gDisableNativeTheme
;
4004 nsresult
NS_NewNativeTheme(nsISupports
*aOuter
, REFNSIID aIID
, void **aResult
)
4006 if (gDisableNativeTheme
)
4007 return NS_ERROR_NO_INTERFACE
;
4010 return NS_ERROR_NO_AGGREGATION
;
4012 nsNativeThemeWin
* theme
= new nsNativeThemeWin();
4014 return NS_ERROR_OUT_OF_MEMORY
;
4015 return theme
->QueryInterface(aIID
, aResult
);