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;
// Same thing but for PP_FILL.
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).
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;
// 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.
static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
@ -674,7 +683,12 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
return NS_OK;
}
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;
return NS_OK;
}
@ -1306,9 +1320,13 @@ RENDER_AGAIN:
else if (aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE) {
OffsetBackgroundRect(widgetRect, CAPTIONBUTTON_CLOSE);
} else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK) {
widgetRect.bottom -= nsUXThemeData::sIsVistaOrLater
? kProgressDeterminedVistaOverflow
: kProgressDeterminedXPOverflow;
nsIFrame* stateFrame = aFrame->GetParent();
nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
widgetRect.bottom -= IsIndeterminateProgress(stateFrame, eventStates)
? kProgressIndeterminateOverflow
: nsUXThemeData::sIsVistaOrLater
? kProgressDeterminedVistaOverflow
: kProgressDeterminedXPOverflow;
}
// widgetRect is the bounding box for a widget, yet the scale track is only
@ -1543,30 +1561,55 @@ RENDER_AGAIN:
ctx->Restore();
ctx->SetOperator(currentOp);
} else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK &&
nsUXThemeData::sIsVistaOrLater) {
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) {
NS_WARNING("unable to animate progress widget!");
} else if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK) {
/**
* 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)) {
NS_WARNING("unable to animate progress widget!");
}
const PRInt32 overlayWidth = nsUXThemeData::sIsVistaOrLater
? kProgressVistaOverlayWidth
: kProgressXPOverlayWidth;
const double pixelsPerMillisecond = indeterminate
? kProgressIndeterminateSpeed
: kProgressDeterminedVistaSpeed;
const PRInt32 frameWidth = widgetRect.right - widgetRect.left;
PRInt32 animationWidth = frameWidth + overlayWidth;
// 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.
double tempValue;
double ratio = modf(PR_IntervalToMilliseconds(PR_IntervalNow())/interval,
&tempValue);
PRInt32 dx = static_cast<PRInt32>(animationWidth * ratio) - overlayWidth;
RECT overlayRect = widgetRect;
overlayRect.left += dx;
overlayRect.right = overlayRect.left + overlayWidth;
nsUXThemeData::drawThemeBG(theme, hdc,
nsUXThemeData::sIsVistaOrLater ? PP_MOVEOVERLAY
: PP_CHUNK,
state, &overlayRect, &clipRect);
}
// Add the animated glow.
const PRInt32 frameWidth = widgetRect.right - widgetRect.left;
static const PRInt32 overlayWidth = kProgressVistaOverlayWidth;
static const double pixelsPerMillisecond = kProgressDeterminedVistaSpeed;
PRInt32 animationWidth = frameWidth + overlayWidth;
double interval = animationWidth / pixelsPerMillisecond;
// We have to pass a double* to modf and we can't pass NULL.
double tempValue;
double ratio = modf(PR_IntervalToMilliseconds(PR_IntervalNow())/interval,
&tempValue);
PRInt32 dx = static_cast<PRInt32>(animationWidth * ratio) - overlayWidth;
RECT overlayRect = widgetRect;
overlayRect.left += dx;
overlayRect.right = overlayRect.left + overlayWidth;
nsUXThemeData::drawThemeBG(theme, hdc, PP_MOVEOVERLAY, state, &overlayRect,
&clipRect);
}