Bug 641905 - Use native rendering for indeterminate progress bar on Windows. r=jimm

This commit is contained in:
Mounir Lamouri 2011-05-04 16:57:48 +02:00
Родитель 0a6a010a11
Коммит 33dc8a610c
1 изменённых файлов: 71 добавлений и 28 удалений

Просмотреть файл

@ -354,10 +354,19 @@ static CaptionButtonPadding buttonData[3] = {
static const PRInt32 kProgressDeterminedXPOverflow = 11; static const PRInt32 kProgressDeterminedXPOverflow = 11;
// Same thing but for PP_FILL. // Same thing but for PP_FILL.
static const PRInt32 kProgressDeterminedVistaOverflow = 4; static const PRInt32 kProgressDeterminedVistaOverflow = 4;
// Same thing but for indeterminate progress bar.
// The value is the same for PP_CHUNK and PP_MOVEOVERLAY in that case.
static const PRInt32 kProgressIndeterminateOverflow = 2;
// The width of the overlay used to animate the progress bar (Vista and later). // The width of the overlay used to animate the progress bar (Vista and later).
static const PRInt32 kProgressVistaOverlayWidth = 120; static const PRInt32 kProgressVistaOverlayWidth = 120;
// Speed of the animation for determined Vista and later progress bars. // The width of the overlay used to for indeterminate progress bars on XP.
static const PRInt32 kProgressXPOverlayWidth = 55;
// Speed (px per ms) of the animation for determined Vista and later progress bars.
static const double kProgressDeterminedVistaSpeed = 0.3; static const double kProgressDeterminedVistaSpeed = 0.3;
// Speed (px per ms) of the animation for indeterminate progress bars.
static const double kProgressIndeterminateSpeed = 0.175;
// Delay between two indeterminate progress bar cycle (in ms).
static const PRInt32 kProgressIndeterminateDelay = 500;
// Adds "hot" caption button padding to minimum widget size. // Adds "hot" caption button padding to minimum widget size.
static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) { static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
@ -674,7 +683,12 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
return NS_OK; return NS_OK;
} }
case NS_THEME_PROGRESSBAR_CHUNK: { case NS_THEME_PROGRESSBAR_CHUNK: {
aPart = nsUXThemeData::sIsVistaOrLater ? PP_FILL : PP_CHUNK; nsIFrame* stateFrame = aFrame->GetParent();
nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
// If the element is indeterminate, we are going to render it ourself so
// we have to return aPart = -1.
aPart = IsIndeterminateProgress(stateFrame, eventStates)
? -1 : nsUXThemeData::sIsVistaOrLater ? PP_FILL : PP_CHUNK;
aState = TS_NORMAL; aState = TS_NORMAL;
return NS_OK; return NS_OK;
} }
@ -1306,7 +1320,11 @@ RENDER_AGAIN:
else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) { else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) {
OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_CLOSE); OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_CLOSE);
} else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK) { } else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK) {
widgetRect.bottom -= nsUXThemeData::sIsVistaOrLater nsIFrame* stateFrame = aFrame->GetParent();
nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
widgetRect.bottom -= IsIndeterminateProgress(stateFrame, eventStates)
? kProgressIndeterminateOverflow
: nsUXThemeData::sIsVistaOrLater
? kProgressDeterminedVistaOverflow ? kProgressDeterminedVistaOverflow
: kProgressDeterminedXPOverflow; : kProgressDeterminedXPOverflow;
} }
@ -1543,19 +1561,41 @@ RENDER_AGAIN:
ctx->Restore(); ctx->Restore();
ctx->SetOperator(currentOp); ctx->SetOperator(currentOp);
} else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK && } else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK) {
nsUXThemeData::sIsVistaOrLater) { /**
* Here, we draw the animated part of the progress bar.
* A progress bar has always an animated part on Windows Vista and later.
* On Windows XP, a progress bar has an animated part when in an
* indeterminated state.
* When the progress bar is indeterminated, no background is painted so we
* only see the animated part.
* When the progress bar is determinated, the animated part is a glow draw
* on top of the background (PP_FILL).
*/
nsIFrame* stateFrame = aFrame->GetParent();
nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
bool indeterminate = IsIndeterminateProgress(stateFrame, eventStates);
if (indeterminate || nsUXThemeData::sIsVistaOrLater) {
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) { if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) {
NS_WARNING("unable to animate progress widget!"); NS_WARNING("unable to animate progress widget!");
} }
// Add the animated glow. const PRInt32 overlayWidth = nsUXThemeData::sIsVistaOrLater
const PRInt32 frameWidth = widgetRect.right - widgetRect.left; ? kProgressVistaOverlayWidth
static const PRInt32 overlayWidth = kProgressVistaOverlayWidth; : kProgressXPOverlayWidth;
static const double pixelsPerMillisecond = kProgressDeterminedVistaSpeed; const double pixelsPerMillisecond = indeterminate
? kProgressIndeterminateSpeed
: kProgressDeterminedVistaSpeed;
const PRInt32 frameWidth = widgetRect.right - widgetRect.left;
PRInt32 animationWidth = frameWidth + overlayWidth; PRInt32 animationWidth = frameWidth + overlayWidth;
double interval = animationWidth / pixelsPerMillisecond; // When indeterminated, we add a delay of one second between two cycles.
if (indeterminate) {
animationWidth += static_cast<PRInt32>(pixelsPerMillisecond *
kProgressIndeterminateDelay);
}
const double interval = animationWidth / pixelsPerMillisecond;
// We have to pass a double* to modf and we can't pass NULL. // We have to pass a double* to modf and we can't pass NULL.
double tempValue; double tempValue;
double ratio = modf(PR_IntervalToMilliseconds(PR_IntervalNow())/interval, double ratio = modf(PR_IntervalToMilliseconds(PR_IntervalNow())/interval,
@ -1565,8 +1605,11 @@ RENDER_AGAIN:
RECT overlayRect = widgetRect; RECT overlayRect = widgetRect;
overlayRect.left += dx; overlayRect.left += dx;
overlayRect.right = overlayRect.left + overlayWidth; overlayRect.right = overlayRect.left + overlayWidth;
nsUXThemeData::drawThemeBG(theme, hdc, PP_MOVEOVERLAY, state, &overlayRect, nsUXThemeData::drawThemeBG(theme, hdc,
&clipRect); nsUXThemeData::sIsVistaOrLater ? PP_MOVEOVERLAY
: PP_CHUNK,
state, &overlayRect, &clipRect);
}
} }