mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Merging cedar with mozilla-central.
This commit is contained in:
commit
0782c0f9f3
@ -91,7 +91,7 @@ test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
|
||||
|
||||
dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
libs:: dummy
|
||||
# Will either crash or return exit code 1 if elfhack is broken
|
||||
|
@ -1394,6 +1394,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
handler.OnQueryDOMWidgetHittest(static_cast<nsQueryContentEvent*>(aEvent));
|
||||
}
|
||||
break;
|
||||
case NS_QUERY_SCROLL_TARGET_INFO:
|
||||
{
|
||||
DoQueryScrollTargetInfo(static_cast<nsQueryContentEvent*>(aEvent),
|
||||
aTargetFrame);
|
||||
break;
|
||||
}
|
||||
case NS_SELECTION_SET:
|
||||
{
|
||||
nsSelectionEvent *selectionEvent =
|
||||
@ -2564,7 +2570,8 @@ nsresult
|
||||
nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
PRBool aAllowScrollSpeedOverride)
|
||||
PRBool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent)
|
||||
{
|
||||
nsIScrollableFrame* frameToScroll = nsnull;
|
||||
nsIFrame* scrollFrame = aTargetFrame;
|
||||
@ -2643,6 +2650,19 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
}
|
||||
|
||||
if (!passToParent && frameToScroll) {
|
||||
if (aQueryEvent) {
|
||||
nscoord appUnitsPerDevPixel =
|
||||
aTargetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
aQueryEvent->mReply.mLineHeight =
|
||||
frameToScroll->GetLineScrollAmount().height / appUnitsPerDevPixel;
|
||||
aQueryEvent->mReply.mPageHeight =
|
||||
frameToScroll->GetPageScrollAmount().height / appUnitsPerDevPixel;
|
||||
aQueryEvent->mReply.mPageWidth =
|
||||
frameToScroll->GetPageScrollAmount().width / appUnitsPerDevPixel;
|
||||
aQueryEvent->mSucceeded = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aScrollQuantity == nsIScrollableFrame::LINES) {
|
||||
numLines =
|
||||
nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
|
||||
@ -2670,7 +2690,9 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsIScrollableFrame::ScrollMode mode;
|
||||
if (aMouseEvent->scrollFlags & nsMouseScrollEvent::kNoDefer) {
|
||||
mode = nsIScrollableFrame::INSTANT;
|
||||
} else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS) {
|
||||
} else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS ||
|
||||
(aMouseEvent->scrollFlags &
|
||||
nsMouseScrollEvent::kAllowSmoothScroll) != 0) {
|
||||
mode = nsIScrollableFrame::SMOOTH;
|
||||
} else {
|
||||
mode = nsIScrollableFrame::NORMAL;
|
||||
@ -2688,7 +2710,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
|
||||
if (newFrame)
|
||||
return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
|
||||
aAllowScrollSpeedOverride);
|
||||
aAllowScrollSpeedOverride, aQueryEvent);
|
||||
}
|
||||
|
||||
aMouseEvent->scrollOverflow = numLines;
|
||||
@ -3051,7 +3073,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_MOUSE_PIXEL_SCROLL) {
|
||||
if (action == MOUSE_SCROLL_N_LINES ||
|
||||
if (action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
|
||||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
|
||||
action = MOUSE_SCROLL_PIXELS;
|
||||
} else {
|
||||
@ -3059,7 +3081,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
action = -1;
|
||||
}
|
||||
} else if (msEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
|
||||
if (action == MOUSE_SCROLL_N_LINES ||
|
||||
if (useSysNumLines || action == MOUSE_SCROLL_N_LINES ||
|
||||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
|
||||
// Don't scroll lines when a pixel scroll event will follow.
|
||||
// Also, don't do history scrolling or zooming for momentum scrolls.
|
||||
@ -4646,6 +4668,20 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame)
|
||||
{
|
||||
nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
|
||||
nsIScrollableFrame::ScrollUnit unit;
|
||||
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage) {
|
||||
unit = nsIScrollableFrame::PAGES;
|
||||
} else {
|
||||
unit = nsIScrollableFrame::LINES;
|
||||
}
|
||||
DoScrollText(aTargetFrame, msEvent, unit, PR_FALSE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
|
||||
nsIContent* aContent)
|
||||
|
@ -324,10 +324,19 @@ protected:
|
||||
nsMouseScrollEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsEventStatus* aStatus);
|
||||
/**
|
||||
* @param aQueryEvent If you set vailid pointer for this, DoScrollText()
|
||||
* computes the line-height and page size of current
|
||||
* mouse wheel scroll target and sets it to the event.
|
||||
* And then, this method does NOT scroll any scrollable
|
||||
* elements. I.e., you can just query the scroll target
|
||||
* information.
|
||||
*/
|
||||
nsresult DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
PRBool aAllowScrollSpeedOverride);
|
||||
PRBool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent = nsnull);
|
||||
void DoScrollHistory(PRInt32 direction);
|
||||
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
|
||||
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
|
||||
@ -397,6 +406,9 @@ protected:
|
||||
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent);
|
||||
|
||||
void DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame);
|
||||
|
||||
PRBool RemoteQueryContentEvent(nsEvent *aEvent);
|
||||
mozilla::dom::TabParent *GetCrossProcessTarget();
|
||||
PRBool IsTargetCrossProcess(nsGUIEvent *aEvent);
|
||||
|
@ -555,6 +555,9 @@ interface nsIDOMCSS2Properties : nsISupports
|
||||
attribute DOMString MozOpacity;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString MozOrient;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString MozOutline;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
|
@ -162,6 +162,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||
#define NS_STYLE_BOX_ORIENT_HORIZONTAL 0
|
||||
#define NS_STYLE_BOX_ORIENT_VERTICAL 1
|
||||
|
||||
// orient
|
||||
#define NS_STYLE_ORIENT_HORIZONTAL 0
|
||||
#define NS_STYLE_ORIENT_VERTICAL 1
|
||||
|
||||
// stack-sizing
|
||||
#define NS_STYLE_STACK_SIZING_IGNORE 0
|
||||
#define NS_STYLE_STACK_SIZING_STRETCH_TO_FIT 1
|
||||
|
@ -171,10 +171,12 @@ nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
bool vertical = GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL;
|
||||
nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame,
|
||||
nsSize(aReflowState.ComputedWidth(),
|
||||
NS_UNCONSTRAINEDSIZE));
|
||||
nscoord width = aReflowState.ComputedWidth();
|
||||
nscoord size = vertical ? aReflowState.ComputedHeight()
|
||||
: aReflowState.ComputedWidth();
|
||||
nscoord xoffset = aReflowState.mComputedBorderPadding.left;
|
||||
nscoord yoffset = aReflowState.mComputedBorderPadding.top;
|
||||
|
||||
@ -183,28 +185,43 @@ nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame,
|
||||
do_QueryInterface(mContent);
|
||||
progressElement->GetPosition(&position);
|
||||
|
||||
// Force the bar's width to match the current progress.
|
||||
// When indeterminate, the progress' width will be 100%.
|
||||
// Force the bar's size to match the current progress.
|
||||
// When indeterminate, the progress' size will be 100%.
|
||||
if (position >= 0.0) {
|
||||
width *= position;
|
||||
size *= position;
|
||||
}
|
||||
|
||||
if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||
xoffset += aReflowState.ComputedWidth() - width;
|
||||
if (!vertical && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||
xoffset += aReflowState.ComputedWidth() - size;
|
||||
}
|
||||
|
||||
// The bar width is fixed in these cases:
|
||||
// - the progress position is determined: the bar width is fixed according
|
||||
// The bar size is fixed in these cases:
|
||||
// - the progress position is determined: the bar size is fixed according
|
||||
// to it's value.
|
||||
// - the progress position is indeterminate and the bar appearance should be
|
||||
// shown as native: the bar width is forced to 100%.
|
||||
// shown as native: the bar size is forced to 100%.
|
||||
// Otherwise (when the progress is indeterminate and the bar appearance isn't
|
||||
// native), the bar width isn't fixed and can be set by the author.
|
||||
// native), the bar size isn't fixed and can be set by the author.
|
||||
if (position != -1 || ShouldUseNativeStyle()) {
|
||||
width -= reflowState.mComputedMargin.LeftRight() +
|
||||
reflowState.mComputedBorderPadding.LeftRight();
|
||||
width = NS_MAX(width, 0);
|
||||
reflowState.SetComputedWidth(width);
|
||||
if (vertical) {
|
||||
// We want the bar to begin at the bottom.
|
||||
yoffset += aReflowState.ComputedHeight() - size;
|
||||
|
||||
size -= reflowState.mComputedMargin.TopBottom() +
|
||||
reflowState.mComputedBorderPadding.TopBottom();
|
||||
size = NS_MAX(size, 0);
|
||||
reflowState.SetComputedHeight(size);
|
||||
} else {
|
||||
size -= reflowState.mComputedMargin.LeftRight() +
|
||||
reflowState.mComputedBorderPadding.LeftRight();
|
||||
size = NS_MAX(size, 0);
|
||||
reflowState.SetComputedWidth(size);
|
||||
}
|
||||
} else if (vertical) {
|
||||
// For vertical progress bars, we need to position the bar specificly when
|
||||
// the width isn't constrained (position == -1 and !ShouldUseNativeStyle())
|
||||
// because aReflowState.ComputedHeight() - size == 0.
|
||||
yoffset += aReflowState.ComputedHeight() - reflowState.ComputedHeight();
|
||||
}
|
||||
|
||||
xoffset += reflowState.mComputedMargin.left;
|
||||
|
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
.progress-element { margin: 10px; }
|
||||
body > div:nth-child(1) > .progress-bar { position: relative; top: 4px; left: 4px;
|
||||
height: -moz-calc(100% - 8px); }
|
||||
body > div:nth-child(2) > .progress-bar { }
|
||||
body > div:nth-child(3) > .progress-bar { position: relative; top: 4px; left: 4px;
|
||||
height: -moz-calc(100% - 8px); }
|
||||
body > div:nth-child(4) > .progress-bar { position: relative; top: 10px; height: -moz-calc(100% - 10px); }
|
||||
body > div:nth-child(5) > .progress-bar { }
|
||||
body > div:nth-child(6) > .progress-bar { height: -moz-calc(100% - 10px); }
|
||||
body > div:nth-child(7) > .progress-bar { position: relative; left: 10px; }
|
||||
body > div:nth-child(8) > .progress-bar { }
|
||||
body > div:nth-child(9) > .progress-bar { }
|
||||
body > div:nth-child(10) > .progress-bar { }
|
||||
body > div:nth-child(11) > .progress-bar { }
|
||||
/* 12 - 15 should have 100% width, no need to specify. */
|
||||
body > div:nth-child(16) > .progress-bar { position: relative; top: 64px; left: 64px;
|
||||
height: -moz-calc(100% + 128px - 1em); }
|
||||
</style>
|
||||
<body>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
.progress-element { margin: 10px; }
|
||||
body > div:nth-child(1) > .progress-bar { position: relative; top: 4px; left: 4px;
|
||||
height: -moz-calc(100% - 8px); }
|
||||
body > div:nth-child(2) > .progress-bar { }
|
||||
body > div:nth-child(3) > .progress-bar { position: relative; top: 4px; left: 4px;
|
||||
height: -moz-calc(100% - 8px); }
|
||||
body > div:nth-child(4) > .progress-bar { position: relative; top: 10px; height: -moz-calc(100% - 10px); }
|
||||
body > div:nth-child(5) > .progress-bar { }
|
||||
body > div:nth-child(6) > .progress-bar { height: -moz-calc(100% - 10px); }
|
||||
body > div:nth-child(7) > .progress-bar { position: relative; left: 10px; }
|
||||
body > div:nth-child(8) > .progress-bar { }
|
||||
body > div:nth-child(9) > .progress-bar { }
|
||||
body > div:nth-child(10) > .progress-bar { }
|
||||
body > div:nth-child(11) > .progress-bar { }
|
||||
/* 12 - 15 should have 100% width, no need to specify. */
|
||||
body > div:nth-child(16) > .progress-bar { position: relative; top: 64px; left: 64px;
|
||||
height: -moz-calc(100% + 128px - 1em); }
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
margin: 10px;
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
body > progress:nth-child(1)::-moz-progress-bar { margin: 4px; padding: 0px; }
|
||||
body > progress:nth-child(2)::-moz-progress-bar { margin: 0px; padding: 4px; }
|
||||
body > progress:nth-child(3)::-moz-progress-bar { margin: 4px; padding: 4px; }
|
||||
body > progress:nth-child(4)::-moz-progress-bar { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
body > progress:nth-child(5)::-moz-progress-bar { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
body > progress:nth-child(6)::-moz-progress-bar { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
body > progress:nth-child(7)::-moz-progress-bar { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
body > progress:nth-child(8)::-moz-progress-bar { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
body > progress:nth-child(9)::-moz-progress-bar { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
body > progress:nth-child(10)::-moz-progress-bar { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
body > progress:nth-child(11)::-moz-progress-bar { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
body > progress:nth-child(12)::-moz-progress-bar { height: 1000px; }
|
||||
body > progress:nth-child(13)::-moz-progress-bar { height: 10px; }
|
||||
body > progress:nth-child(14)::-moz-progress-bar { height: 10%; }
|
||||
body > progress:nth-child(15)::-moz-progress-bar { height: 200%; }
|
||||
body > progress:nth-child(16)::-moz-progress-bar { margin: 64px; padding: 64px; }
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<!-- Those will be used to change padding/margin on ::-moz-progress-bar -->
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<!-- Those will be used to change width. -->
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
margin: 10px;
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
body > progress:nth-child(1)::-moz-progress-bar { margin: 4px; padding: 0px; }
|
||||
body > progress:nth-child(2)::-moz-progress-bar { margin: 0px; padding: 4px; }
|
||||
body > progress:nth-child(3)::-moz-progress-bar { margin: 4px; padding: 4px; }
|
||||
body > progress:nth-child(4)::-moz-progress-bar { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
body > progress:nth-child(5)::-moz-progress-bar { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
body > progress:nth-child(6)::-moz-progress-bar { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
body > progress:nth-child(7)::-moz-progress-bar { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
body > progress:nth-child(8)::-moz-progress-bar { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
body > progress:nth-child(9)::-moz-progress-bar { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
body > progress:nth-child(10)::-moz-progress-bar { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
body > progress:nth-child(11)::-moz-progress-bar { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
body > progress:nth-child(12)::-moz-progress-bar { height: 1000px; }
|
||||
body > progress:nth-child(13)::-moz-progress-bar { height: 10px; }
|
||||
body > progress:nth-child(14)::-moz-progress-bar { height: 10%; }
|
||||
body > progress:nth-child(15)::-moz-progress-bar { height: 200%; }
|
||||
body > progress:nth-child(16)::-moz-progress-bar { margin: 64px; padding: 64px; }
|
||||
</style>
|
||||
<body>
|
||||
<!-- Those will be used to change padding/margin on ::-moz-progress-bar -->
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<!-- Those will be used to change width. -->
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
div.progress-element {
|
||||
height: 12em;
|
||||
width: 2em;
|
||||
}
|
||||
div.progress-bar {
|
||||
height: 100%;
|
||||
}
|
||||
body > div:nth-child(1) > .progress-bar { position: relative;
|
||||
top: -moz-calc(12em - 20px); height: 20px; }
|
||||
body > div:nth-child(2) > .progress-bar { position: relative;
|
||||
top: -moz-calc(12em - 0px); height: 0px; }
|
||||
body > div:nth-child(3) > .progress-bar { position: relative;
|
||||
top: -moz-calc(12em - 50%); height: 50%; }
|
||||
body > div:nth-child(4) > .progress-bar { position: relative;
|
||||
top: -moz-calc(12em - 1em); height: 1em; }
|
||||
body > div:nth-child(5) > .progress-bar { position: relative;
|
||||
top: -moz-calc(12em - 100%); height: 100%; }
|
||||
</style>
|
||||
<body>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
-moz-orient: vertical;
|
||||
height: 12em;
|
||||
width: 2em;
|
||||
}
|
||||
body > progress:nth-child(1)::-moz-progress-bar { height: 20px; }
|
||||
body > progress:nth-child(2)::-moz-progress-bar { height: 0px; }
|
||||
body > progress:nth-child(3)::-moz-progress-bar { height: 50%; }
|
||||
body > progress:nth-child(4)::-moz-progress-bar { height: 1em; }
|
||||
/* last one is for the default value: width=100%. */
|
||||
</style>
|
||||
<body>
|
||||
<!-- Those will be used to change padding/margin on ::-moz-progress-bar -->
|
||||
<progress></progress>
|
||||
<progress></progress>
|
||||
<progress></progress>
|
||||
<progress></progress>
|
||||
<progress></progress>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
body > div:nth-child(1) { margin: 10px; padding: 0px; }
|
||||
body > div:nth-child(2) { margin: 0px; padding: 10px; }
|
||||
body > div:nth-child(3) { margin: 10px; padding: 10px; }
|
||||
body > div:nth-child(4) { margin: 5px; padding: 5px; }
|
||||
body > div:nth-child(5) { margin: 50px; padding: 50px; }
|
||||
body > div:nth-child(6) { margin: 100px; padding: 100px; }
|
||||
body > div:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
body > div:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
body > div:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
body > div:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
body > div:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
body > div:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
body > div:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
body > div:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
body > div:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
|
||||
body > div:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
|
||||
</style>
|
||||
<body>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
body > div:nth-child(1) { margin: 10px; padding: 0px; }
|
||||
body > div:nth-child(2) { margin: 0px; padding: 10px; }
|
||||
body > div:nth-child(3) { margin: 10px; padding: 10px; }
|
||||
body > div:nth-child(4) { margin: 5px; padding: 5px; }
|
||||
body > div:nth-child(5) { margin: 50px; padding: 50px; }
|
||||
body > div:nth-child(6) { margin: 100px; padding: 100px; }
|
||||
body > div:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
body > div:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
body > div:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
body > div:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
body > div:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
body > div:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
body > div:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
body > div:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
body > div:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
|
||||
body > div:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
progress:nth-child(1) { margin: 10px; padding: 0px; }
|
||||
progress:nth-child(2) { margin: 0px; padding: 10px; }
|
||||
progress:nth-child(3) { margin: 10px; padding: 10px; }
|
||||
progress:nth-child(4) { margin: 5px; padding: 5px; }
|
||||
progress:nth-child(5) { margin: 50px; padding: 50px; }
|
||||
progress:nth-child(6) { margin: 100px; padding: 100px; }
|
||||
progress:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
progress:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
progress:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
progress:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
progress:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
progress:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
progress:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
progress:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
progress:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
|
||||
progress:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
</body>
|
||||
</html>
|
43
layout/reftests/forms/progress/margin-padding-vertical.html
Normal file
43
layout/reftests/forms/progress/margin-padding-vertical.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
progress:nth-child(1) { margin: 10px; padding: 0px; }
|
||||
progress:nth-child(2) { margin: 0px; padding: 10px; }
|
||||
progress:nth-child(3) { margin: 10px; padding: 10px; }
|
||||
progress:nth-child(4) { margin: 5px; padding: 5px; }
|
||||
progress:nth-child(5) { margin: 50px; padding: 50px; }
|
||||
progress:nth-child(6) { margin: 100px; padding: 100px; }
|
||||
progress:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
|
||||
progress:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
|
||||
progress:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
|
||||
progress:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
|
||||
progress:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
|
||||
progress:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
|
||||
progress:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
|
||||
progress:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
|
||||
progress:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
|
||||
progress:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
|
||||
</style>
|
||||
<body>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
<progress value='1'></progress>
|
||||
</body>
|
||||
</html>
|
@ -6,6 +6,15 @@
|
||||
== bar-pseudo-element-rtl.html bar-pseudo-element-rtl-ref.html
|
||||
== indeterminate-style-width.html indeterminate-style-width-ref.html
|
||||
|
||||
# vertical tests
|
||||
== values-vertical.html values-vertical-ref.html
|
||||
== values-vertical-rtl.html values-vertical-rtl-ref.html
|
||||
== margin-padding-vertical.html margin-padding-vertical-ref.html
|
||||
== margin-padding-vertical-rtl.html margin-padding-vertical-rtl-ref.html
|
||||
== bar-pseudo-element-vertical.html bar-pseudo-element-vertical-ref.html
|
||||
== bar-pseudo-element-vertical-rtl.html bar-pseudo-element-vertical-rtl-ref.html
|
||||
== indeterminate-style-height.html indeterminate-style-height-ref.html
|
||||
|
||||
# The following test is disabled but kept in the repository because the
|
||||
# transformations will not behave exactly the same for <progress> and two divs.
|
||||
# However, it would be possible to manually check those.
|
||||
|
58
layout/reftests/forms/progress/values-vertical-ref.html
Normal file
58
layout/reftests/forms/progress/values-vertical-ref.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
div:nth-child(1) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(2) > .progress-bar { position: relative; top: 100%; height: 0%; }
|
||||
div:nth-child(3) > .progress-bar { position: relative; top: 90%; height: 10%; }
|
||||
div:nth-child(4) > .progress-bar { position: relative; top: 50%; height: 50%; }
|
||||
div:nth-child(5) > .progress-bar { position: relative; top: 100%; height: 0%; }
|
||||
div:nth-child(6) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(7) > .progress-bar { position: relative; top: 58%; height: 42%; }
|
||||
div:nth-child(8) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(9) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(10) > .progress-bar { position: relative; top: 90%; height: 10%; }
|
||||
</style>
|
||||
<body>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
58
layout/reftests/forms/progress/values-vertical-rtl-ref.html
Normal file
58
layout/reftests/forms/progress/values-vertical-rtl-ref.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
div:nth-child(1) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(2) > .progress-bar { position: relative; top: 100%; height: 0%; }
|
||||
div:nth-child(3) > .progress-bar { position: relative; top: 90%; height: 10%; }
|
||||
div:nth-child(4) > .progress-bar { position: relative; top: 50%; height: 50%; }
|
||||
div:nth-child(5) > .progress-bar { position: relative; top: 100%; height: 0%; }
|
||||
div:nth-child(6) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(7) > .progress-bar { position: relative; top: 58%; height: 42%; }
|
||||
div:nth-child(8) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(9) > .progress-bar { position: relative; top: 0%; height: 100%; }
|
||||
div:nth-child(10) > .progress-bar { position: relative; top: 90%; height: 10%; }
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-element">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/forms/progress/values-vertical-rtl.html
Normal file
21
layout/reftests/forms/progress/values-vertical-rtl.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
</style>
|
||||
<body dir='rtl'>
|
||||
<progress value="1.0"></progress>
|
||||
<progress value="0.0"></progress>
|
||||
<progress value="0.1"></progress>
|
||||
<progress value="0.5"></progress>
|
||||
<progress value="-1"></progress>
|
||||
<progress value="42"></progress>
|
||||
<progress value="42" max="100"></progress>
|
||||
<progress value="42" max="1"></progress>
|
||||
<progress value="42" max="-1"></progress>
|
||||
<progress value="0.1" max="-1"></progress>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/forms/progress/values-vertical.html
Normal file
21
layout/reftests/forms/progress/values-vertical.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<style>
|
||||
progress {
|
||||
-moz-orient: vertical;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<progress value="1.0"></progress>
|
||||
<progress value="0.0"></progress>
|
||||
<progress value="0.1"></progress>
|
||||
<progress value="0.5"></progress>
|
||||
<progress value="-1"></progress>
|
||||
<progress value="42"></progress>
|
||||
<progress value="42" max="100"></progress>
|
||||
<progress value="42" max="1"></progress>
|
||||
<progress value="42" max="-1"></progress>
|
||||
<progress value="0.1" max="-1"></progress>
|
||||
</body>
|
||||
</html>
|
@ -1813,6 +1813,15 @@ CSS_PROP_DISPLAY(
|
||||
nsnull,
|
||||
offsetof(nsStyleDisplay, mOpacity),
|
||||
eStyleAnimType_float) // XXX bug 3935
|
||||
CSS_PROP_DISPLAY(
|
||||
-moz-orient,
|
||||
orient,
|
||||
CSS_PROP_DOMPROP_PREFIXED(Orient),
|
||||
CSS_PROPERTY_PARSE_VALUE,
|
||||
VARIANT_HK,
|
||||
kOrientKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_None)
|
||||
CSS_PROP_BACKENDONLY(
|
||||
orphans,
|
||||
orphans,
|
||||
|
@ -1038,6 +1038,12 @@ const PRInt32 nsCSSProps::kListStyleKTable[] = {
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
};
|
||||
|
||||
const PRInt32 nsCSSProps::kOrientKTable[] = {
|
||||
eCSSKeyword_horizontal, NS_STYLE_ORIENT_HORIZONTAL,
|
||||
eCSSKeyword_vertical, NS_STYLE_ORIENT_VERTICAL,
|
||||
eCSSKeyword_UNKNOWN, -1
|
||||
};
|
||||
|
||||
// Same as kBorderStyleKTable except 'hidden'.
|
||||
const PRInt32 nsCSSProps::kOutlineStyleKTable[] = {
|
||||
eCSSKeyword_none, NS_STYLE_BORDER_STYLE_NONE,
|
||||
|
@ -383,6 +383,7 @@ public:
|
||||
static const PRInt32 kLineHeightKTable[];
|
||||
static const PRInt32 kListStylePositionKTable[];
|
||||
static const PRInt32 kListStyleKTable[];
|
||||
static const PRInt32 kOrientKTable[];
|
||||
static const PRInt32 kOutlineStyleKTable[];
|
||||
static const PRInt32 kOutlineColorKTable[];
|
||||
static const PRInt32 kOverflowKTable[];
|
||||
|
@ -1912,6 +1912,16 @@ nsComputedDOMStyle::DoGetMarkerOffset()
|
||||
return val;
|
||||
}
|
||||
|
||||
nsIDOMCSSValue*
|
||||
nsComputedDOMStyle::DoGetOrient()
|
||||
{
|
||||
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
|
||||
val->SetIdent(
|
||||
nsCSSProps::ValueToKeywordEnum(GetStyleDisplay()->mOrient,
|
||||
nsCSSProps::kOrientKTable));
|
||||
return val;
|
||||
}
|
||||
|
||||
nsIDOMCSSValue*
|
||||
nsComputedDOMStyle::DoGetOutline()
|
||||
{
|
||||
@ -4392,6 +4402,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
|
||||
COMPUTED_STYLE_MAP_ENTRY(marker_end, MarkerEnd),
|
||||
COMPUTED_STYLE_MAP_ENTRY(marker_mid, MarkerMid),
|
||||
COMPUTED_STYLE_MAP_ENTRY(marker_start, MarkerStart),
|
||||
COMPUTED_STYLE_MAP_ENTRY(orient, Orient),
|
||||
COMPUTED_STYLE_MAP_ENTRY(shape_rendering, ShapeRendering),
|
||||
COMPUTED_STYLE_MAP_ENTRY(stop_color, StopColor),
|
||||
COMPUTED_STYLE_MAP_ENTRY(stop_opacity, StopOpacity),
|
||||
|
@ -346,6 +346,7 @@ private:
|
||||
nsIDOMCSSValue* DoGetPageBreakBefore();
|
||||
nsIDOMCSSValue* DoGetMozTransform();
|
||||
nsIDOMCSSValue* DoGetMozTransformOrigin();
|
||||
nsIDOMCSSValue* DoGetOrient();
|
||||
|
||||
/* User interface properties */
|
||||
nsIDOMCSSValue* DoGetCursor();
|
||||
|
@ -4482,6 +4482,12 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
|
||||
NS_ASSERTION(result, "Malformed -moz-transform-origin parse!");
|
||||
}
|
||||
|
||||
// orient: enum, inherit, initial
|
||||
SetDiscrete(*aRuleData->ValueForOrient(),
|
||||
display->mOrient, canStoreInRuleTree,
|
||||
SETDSC_ENUMERATED, parentDisplay->mOrient,
|
||||
NS_STYLE_ORIENT_HORIZONTAL, 0, 0, 0, 0);
|
||||
|
||||
COMPUTE_END_RESET(Display, display)
|
||||
}
|
||||
|
||||
|
@ -2029,6 +2029,7 @@ nsStyleDisplay::nsStyleDisplay()
|
||||
mSpecifiedTransform = nsnull;
|
||||
mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
|
||||
mTransformOrigin[1].SetPercentValue(0.5f);
|
||||
mOrient = NS_STYLE_ORIENT_HORIZONTAL;
|
||||
|
||||
mTransitions.AppendElement();
|
||||
NS_ABORT_IF_FALSE(mTransitions.Length() == 1,
|
||||
@ -2089,6 +2090,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
|
||||
mClipFlags = aSource.mClipFlags;
|
||||
mClip = aSource.mClip;
|
||||
mOpacity = aSource.mOpacity;
|
||||
mOrient = aSource.mOrient;
|
||||
|
||||
/* Copy over the transformation information. */
|
||||
mSpecifiedTransform = aSource.mSpecifiedTransform;
|
||||
@ -2127,6 +2129,7 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|
||||
|| mBreakBefore != aOther.mBreakBefore
|
||||
|| mBreakAfter != aOther.mBreakAfter
|
||||
|| mAppearance != aOther.mAppearance
|
||||
|| mOrient != aOther.mOrient
|
||||
|| mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip))
|
||||
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
|
||||
|
||||
|
@ -1514,6 +1514,7 @@ struct nsStyleDisplay {
|
||||
PRUint8 mOverflowY; // [reset] see nsStyleConsts.h
|
||||
PRUint8 mResize; // [reset] see nsStyleConsts.h
|
||||
PRUint8 mClipFlags; // [reset] see nsStyleConsts.h
|
||||
PRUint8 mOrient; // [reset] see nsStyleConsts.h
|
||||
|
||||
// mSpecifiedTransform is the list of transform functions as
|
||||
// specified, or null to indicate there is no transform. (inherit or
|
||||
|
@ -2161,6 +2161,14 @@ var gCSSProperties = {
|
||||
other_values: [ "0", "0.4", "0.0000", "-3" ],
|
||||
invalid_values: [ "0px", "1px" ]
|
||||
},
|
||||
"-moz-orient": {
|
||||
domProp: "MozOrient",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "horizontal" ],
|
||||
other_values: [ "vertical" ],
|
||||
invalid_values: [ "auto", "none" ]
|
||||
},
|
||||
"orphans": {
|
||||
domProp: "orphans",
|
||||
inherited: true,
|
||||
|
@ -172,7 +172,8 @@ pref("signon.expireMasterPassword", false);
|
||||
pref("signon.SignonFileName", "signons.txt");
|
||||
|
||||
/* form helper */
|
||||
pref("formhelper.enabled", true);
|
||||
// 0 = disabled, 1 = enabled, 2 = dynamic depending on screen size
|
||||
pref("formhelper.mode", 2);
|
||||
pref("formhelper.autozoom", true);
|
||||
pref("formhelper.autozoom.caret", true);
|
||||
pref("formhelper.restore", false);
|
||||
|
@ -161,6 +161,13 @@ let Util = {
|
||||
return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
|
||||
},
|
||||
|
||||
isTablet: function isTablet() {
|
||||
// See the tablet_panel_minwidth from mobile/themes/core/defines.inc
|
||||
let tablet_panel_minwidth = 124;
|
||||
let dpmm = Util.getWindowUtils(window).displayDPI / 25.4;
|
||||
return (window.innerWidth / dpmm <= tablet_panel_minwidth);
|
||||
},
|
||||
|
||||
isPortrait: function isPortrait() {
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
return (screen.width <= screen.height);
|
||||
|
@ -98,6 +98,7 @@
|
||||
<script type="application/javascript;version=1.8"><![CDATA[
|
||||
let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
||||
let gChromeWin = null;
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
function openLink(aElement) {
|
||||
try {
|
||||
@ -308,9 +309,10 @@
|
||||
list.removeChild(header.nextSibling);
|
||||
|
||||
for (let i=0; i<aAddons.length; i++) {
|
||||
let addon = aAddons[i];
|
||||
let outer = document.createElement("div");
|
||||
outer.setAttribute("role", "button");
|
||||
outer.setAttribute("addonID", aAddons[i].id);
|
||||
outer.setAttribute("addonID", addon.id);
|
||||
|
||||
let addonName = aAddons[i].name;
|
||||
outer.addEventListener("click", function() {
|
||||
@ -319,19 +321,19 @@
|
||||
|
||||
let img = document.createElement("img");
|
||||
img.className = "favicon";
|
||||
img.setAttribute("src", aAddons[i].iconURL);
|
||||
img.setAttribute("src", addon.iconURL);
|
||||
outer.appendChild(img);
|
||||
|
||||
let inner = document.createElement("div");
|
||||
inner.className = "inner";
|
||||
|
||||
let titlePart = document.createElement("span");
|
||||
titlePart.textContent = aAddons[i].name;
|
||||
titlePart.textContent = addon.name;
|
||||
titlePart.className = "title";
|
||||
inner.appendChild(titlePart);
|
||||
|
||||
let versionPart = document.createElement("span");
|
||||
versionPart.textContent = aAddons[i].version;
|
||||
versionPart.textContent = addon.version;
|
||||
versionPart.className = "version";
|
||||
inner.appendChild(versionPart);
|
||||
|
||||
@ -344,7 +346,21 @@
|
||||
let file = this._getFile();
|
||||
if (file.exists()) {
|
||||
let json = JSON.parse(this._readFile(file));
|
||||
this._loadAddons(json.addons, json.addonCount, json.totalResults);
|
||||
|
||||
// Ignore addons already installed
|
||||
let self = this;
|
||||
let addonsCache = json.addons;
|
||||
AddonManager.getAllAddons(function(aAddons) {
|
||||
let addons = addonsCache.filter(function(addon) {
|
||||
for (let i =0; i < aAddons.length; i++)
|
||||
if (addon.id == aAddons[i].id)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
self._loadAddons(addons, addons.length, json.totalResults);
|
||||
});
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
let aus = Cc["@mozilla.org/browser/addon-update-service;1"].getService(Ci.nsITimerCallback);
|
||||
|
@ -1254,17 +1254,25 @@
|
||||
</handler>
|
||||
</handlers>
|
||||
<content orient="vertical" flex="1">
|
||||
<xul:hbox class="history-throbber-box" flex="1" align="center" pack="center">
|
||||
<xul:image src="chrome://browser/skin/images/throbber.png" />
|
||||
</xul:hbox>
|
||||
<xul:richlistbox anonid="child-items" class="history-list-children" flex="1" batch="25"/>
|
||||
</content>
|
||||
<implementation>
|
||||
<method name="open">
|
||||
<body><![CDATA[
|
||||
let children = this._children;
|
||||
while (children.lastChild)
|
||||
children.removeChild(children.lastChild);
|
||||
this.setAttribute("loading", "true");
|
||||
|
||||
let items = this._getHistory();
|
||||
children.setItems(items.map(this.createItem));
|
||||
setTimeout(function(self) {
|
||||
let children = self._children;
|
||||
while (children.lastChild)
|
||||
children.removeChild(children.lastChild);
|
||||
|
||||
let items = self._getHistory();
|
||||
children.setItems(items.map(self.createItem));
|
||||
self.removeAttribute("loading");
|
||||
}, 0, this);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -1364,17 +1372,25 @@
|
||||
</handler>
|
||||
</handlers>
|
||||
<content orient="vertical" flex="1">
|
||||
<xul:hbox class="remotetabs-throbber-box" flex="1" align="center" pack="center">
|
||||
<xul:image src="chrome://browser/skin/images/throbber.png" />
|
||||
</xul:hbox>
|
||||
<xul:richlistbox anonid="child-items" class="remotetabs-list-children" flex="1" batch="25"/>
|
||||
</content>
|
||||
<implementation>
|
||||
<method name="open">
|
||||
<body><![CDATA[
|
||||
let children = this._children;
|
||||
while (children.lastChild)
|
||||
children.removeChild(children.lastChild);
|
||||
this.setAttribute("loading", "true");
|
||||
|
||||
let items = this._getRemoteTabs();
|
||||
children.setItems(items.map(this.createItem));
|
||||
setTimeout(function(self) {
|
||||
let children = self._children;
|
||||
while (children.lastChild)
|
||||
children.removeChild(children.lastChild);
|
||||
|
||||
let items = self._getRemoteTabs();
|
||||
children.setItems(items.map(self.createItem));
|
||||
self.removeAttribute("loading");
|
||||
}, 0, this);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -1196,15 +1196,11 @@ var BrowserUI = {
|
||||
this.activePanel = HistoryList;
|
||||
break;
|
||||
case "cmd_remoteTabs":
|
||||
// remove the checked state set by the click it will be reset by setting
|
||||
// checked on the command element if we decide to show this panel (see AwesomePanel.js)
|
||||
document.getElementById("remotetabs-button").removeAttribute("checked");
|
||||
|
||||
if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED) {
|
||||
this.activePanel = null;
|
||||
|
||||
WeaveGlue.open();
|
||||
} else if (!Weave.Service.isLoggedIn) {
|
||||
// unchecked the relative command button
|
||||
document.getElementById("remotetabs-button").removeAttribute("checked");
|
||||
this.activePanel = null;
|
||||
|
||||
BrowserUI.showPanel("prefs-container");
|
||||
@ -1217,9 +1213,11 @@ var BrowserUI = {
|
||||
prefsBox.scrollBoxObject.scrollTo(0, syncAreaY - prefsBoxY);
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
this.activePanel = RemoteTabsList;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.activePanel = RemoteTabsList;
|
||||
break;
|
||||
case "cmd_quit":
|
||||
GlobalOverlay.goQuitApplication();
|
||||
|
@ -675,6 +675,12 @@ var FormHelperUI = {
|
||||
// Listen some events to show/hide arrows
|
||||
Elements.browsers.addEventListener("PanBegin", this, false);
|
||||
Elements.browsers.addEventListener("PanFinished", this, false);
|
||||
|
||||
// Dynamically enabled/disabled the form helper if needed depending on
|
||||
// the size of the screen
|
||||
let mode = Services.prefs.getIntPref("formhelper.mode");
|
||||
let state = (mode == 2) ? !Util.isTablet() : !!mode;
|
||||
Services.prefs.setBoolPref("formhelper.enabled", state);
|
||||
},
|
||||
|
||||
_currentBrowser: null,
|
||||
@ -792,22 +798,34 @@ var FormHelperUI = {
|
||||
},
|
||||
|
||||
receiveMessage: function formHelperReceiveMessage(aMessage) {
|
||||
if (!this._open && aMessage.name != "FormAssist:Show" && aMessage.name != "FormAssist:Hide")
|
||||
let allowedMessages = ["FormAssist:Show", "FormAssist:Hide", "FormAssist:AutoComplete"];
|
||||
if (!this._open && allowedMessages.indexOf(aMessage.name) == -1)
|
||||
return;
|
||||
|
||||
let json = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "FormAssist:Show":
|
||||
// if the user has manually disabled the Form Assistant UI we still
|
||||
// want to show a UI for <select /> element but not managed by
|
||||
// FormHelperUI
|
||||
this.enabled ? this.show(json.current, json.hasPrevious, json.hasNext)
|
||||
: SelectHelperUI.show(json.current.choices, json.current.title);
|
||||
// want to show a UI for <select /> element and still want to show
|
||||
// autocomplete suggestions but not managed by FormHelperUI
|
||||
if (this.enabled) {
|
||||
this.show(json.current, json.hasPrevious, json.hasNext)
|
||||
} else if (json.current.choices) {
|
||||
SelectHelperUI.show(json.current.choices, json.current.title);
|
||||
} else {
|
||||
this._currentElementRect = Rect.fromRect(json.current.rect);
|
||||
this._currentBrowser = getBrowser();
|
||||
this._updateSuggestionsFor(json.current);
|
||||
}
|
||||
break;
|
||||
|
||||
case "FormAssist:Hide":
|
||||
this.enabled ? this.hide()
|
||||
: SelectHelperUI.hide();
|
||||
if (this.enabled) {
|
||||
this.hide();
|
||||
} else {
|
||||
SelectHelperUI.hide();
|
||||
ContentPopupHelper.popup = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case "FormAssist:Resize":
|
||||
|
@ -179,10 +179,12 @@ FormAssistant.prototype = {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If form assistant is disabled but the element is a type of choice list
|
||||
// we still want to show the simple select list
|
||||
// There is some case where we still want some data to be send to the
|
||||
// parent process even if form assistant is disabled:
|
||||
// - the element is a choice list
|
||||
// - the element has autocomplete suggestions
|
||||
this._enabled = Services.prefs.getBoolPref("formhelper.enabled");
|
||||
if (!this._enabled && !this._isSelectElement(aElement))
|
||||
if (!this._enabled && !this._isSelectElement(aElement) && !this._isAutocomplete(aElement))
|
||||
return this.close();
|
||||
|
||||
if (this._enabled) {
|
||||
@ -210,7 +212,7 @@ FormAssistant.prototype = {
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
let currentElement = this.currentElement;
|
||||
if ((!this._enabled && !getWrapperForElement(currentElement)) || !currentElement)
|
||||
if ((!this._enabled && !this._isAutocomplete(currentElement) && !getWrapperForElement(currentElement)) || !currentElement)
|
||||
return;
|
||||
|
||||
let json = aMessage.json;
|
||||
@ -729,8 +731,8 @@ FormAssistant.prototype = {
|
||||
maxLength: element.maxLength,
|
||||
type: (element.getAttribute("type") || "").toLowerCase(),
|
||||
choices: choices,
|
||||
isAutocomplete: this._isAutocomplete(this.currentElement),
|
||||
list: this._getListSuggestions(this.currentElement),
|
||||
isAutocomplete: this._isAutocomplete(element),
|
||||
list: this._getListSuggestions(element),
|
||||
rect: this._getRect(),
|
||||
caretRect: this._getCaretRect()
|
||||
},
|
||||
|
@ -414,6 +414,28 @@ toolbarbutton.choice-remotetabs {
|
||||
list-style-image: url(chrome://browser/skin/images/remotetabs-48.png);
|
||||
}
|
||||
|
||||
/* awesomescreen panels ---------------------------------------------------- */
|
||||
historylist > hbox.history-throbber-box,
|
||||
remotetabslist > hbox.remotetabs-throbber-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.history-throbber-box > image,
|
||||
.remotetabs-throbber-box > image {
|
||||
list-style-image: url("chrome://browser/skin/images/throbber.png");
|
||||
}
|
||||
|
||||
historylist[loading="true"] > hbox.history-throbber-box,
|
||||
remotetabslist[loading="true"] > hbox.remotetabs-throbber-box {
|
||||
background-color: white;
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
historylist[loading="true"] > richlistbox.history-list-children,
|
||||
remotetabslist[loading="true"] > richlistbox.remotetabs-list-children {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
/* browsers ---------------------------------------------------------------- */
|
||||
.input-overlay:-moz-focusring {
|
||||
outline: 0 !important;
|
||||
|
@ -1,10 +1,12 @@
|
||||
var timer;
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
response.write("ok(true, 'Slow script ran.');");
|
||||
response.processAsync();
|
||||
var timer = Components.classes["@mozilla.org/timer;1"]
|
||||
timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback(function() {
|
||||
response.finish();
|
||||
|
@ -235,12 +235,25 @@ TelemetryPing.prototype = {
|
||||
let idleService = Cc["@mozilla.org/widget/idleservice;1"].
|
||||
getService(Ci.nsIIdleService);
|
||||
idleService.addIdleObserver(self, TELEMETRY_INTERVAL);
|
||||
Services.obs.addObserver(self, "idle-daily", null);
|
||||
Services.obs.addObserver(self, "idle-daily", false);
|
||||
Services.obs.addObserver(self, "profile-before-change", false);
|
||||
self.gatherMemory();
|
||||
delete self._timer
|
||||
}
|
||||
this._timer.initWithCallback(timerCallback, TELEMETRY_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove observers to avoid leaks
|
||||
*/
|
||||
uninstall: function uninstall() {
|
||||
let idleService = Cc["@mozilla.org/widget/idleservice;1"].
|
||||
getService(Ci.nsIIdleService);
|
||||
idleService.removeIdleObserver(this, TELEMETRY_INTERVAL);
|
||||
Services.obs.removeObserver(this, "idle-daily");
|
||||
Services.obs.removeObserver(this, "profile-before-change");
|
||||
},
|
||||
|
||||
/**
|
||||
* This observer drives telemetry.
|
||||
*/
|
||||
@ -252,6 +265,9 @@ TelemetryPing.prototype = {
|
||||
case "profile-after-change":
|
||||
this.setup();
|
||||
break;
|
||||
case "profile-before-change":
|
||||
this.uninstall();
|
||||
break;
|
||||
case "idle":
|
||||
this.gatherMemory();
|
||||
break;
|
||||
|
@ -132,6 +132,16 @@ else
|
||||
SDK_LIBRARY = $(SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
# See bug 653662 - some builders are hitting an internal size limit
|
||||
# on incremental builds. Disable this for debug builds for now. We may
|
||||
# be able to revisit this after our builders are upgraded to something
|
||||
# later than Visual Studio 2005.
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef MOZ_DEBUG
|
||||
EXTRA_DSO_LDOPTS += -INCREMENTAL:NO
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(EXTRA_DSO_LIBS)
|
||||
|
||||
ifndef MOZ_ENABLE_LIBXUL
|
||||
|
@ -440,16 +440,21 @@ function UpdateParser(aId, aType, aUpdateKey, aUrl, aObserver) {
|
||||
}
|
||||
|
||||
LOG("Requesting " + aUrl);
|
||||
this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
this.request.open("GET", aUrl, true);
|
||||
this.request.channel.notificationCallbacks = new BadCertHandler(!requireBuiltIn);
|
||||
this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
this.request.overrideMimeType("text/xml");
|
||||
var self = this;
|
||||
this.request.onload = function(event) { self.onLoad() };
|
||||
this.request.onerror = function(event) { self.onError() };
|
||||
this.request.send(null);
|
||||
try {
|
||||
this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
this.request.open("GET", aUrl, true);
|
||||
this.request.channel.notificationCallbacks = new BadCertHandler(!requireBuiltIn);
|
||||
this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
this.request.overrideMimeType("text/xml");
|
||||
var self = this;
|
||||
this.request.onload = function(event) { self.onLoad() };
|
||||
this.request.onerror = function(event) { self.onError() };
|
||||
this.request.send(null);
|
||||
}
|
||||
catch (e) {
|
||||
ERROR("Failed to request update manifest", e);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateParser.prototype = {
|
||||
|
@ -344,7 +344,7 @@ SafeInstallOperation.prototype = {
|
||||
function getLocale() {
|
||||
if (Prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false))
|
||||
return Services.locale.getLocaleComponentForUserAgent();
|
||||
let locale = Prefs.getComplexPref(PREF_SELECTED_LOCALE, Ci.nsIPrefLocalizedString);
|
||||
let locale = Prefs.getComplexValue(PREF_SELECTED_LOCALE, Ci.nsIPrefLocalizedString);
|
||||
if (locale)
|
||||
return locale;
|
||||
return Prefs.getCharPref(PREF_SELECTED_LOCALE, "en-US");
|
||||
@ -1229,9 +1229,9 @@ var Prefs = {
|
||||
* A value to return if the preference does not exist
|
||||
* @return the value of the preference or aDefaultValue if there is none
|
||||
*/
|
||||
getComplexPref: function(aName, aType, aDefaultValue) {
|
||||
getComplexValue: function(aName, aType, aDefaultValue) {
|
||||
try {
|
||||
return Services.prefs.getComplexPref(aName, aType).data;
|
||||
return Services.prefs.getComplexValue(aName, aType).data;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
@ -246,8 +246,8 @@ function getLocale() {
|
||||
try {
|
||||
// Get the default branch
|
||||
var defaultPrefs = gPref.getDefaultBranch(null);
|
||||
return defaultPrefs.getComplexPref(PREF_GENERAL_USERAGENT_LOCALE,
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
return defaultPrefs.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE,
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
} catch (e) {}
|
||||
|
||||
return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
|
||||
|
@ -22,11 +22,29 @@ var gTests = [];
|
||||
var gStart = 0;
|
||||
var gLast = 0;
|
||||
|
||||
var HTTPObserver = {
|
||||
observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData,
|
||||
aStringData) {
|
||||
aChannel.QueryInterface(Ci.nsIChannel);
|
||||
|
||||
dump("*** HTTP Activity 0x" + aType.toString(16) + " 0x" + aSubtype.toString(16) +
|
||||
" " + aChannel.URI.spec + "\n");
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
gStart = Date.now();
|
||||
requestLongerTimeout(4);
|
||||
waitForExplicitFinish();
|
||||
|
||||
let observerService = Cc["@mozilla.org/network/http-activity-distributor;1"].
|
||||
getService(Ci.nsIHttpActivityDistributor);
|
||||
observerService.addObserver(HTTPObserver);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
observerService.removeObserver(HTTPObserver);
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
<center>
|
||||
<h1>The Jprof Profiler</h1>
|
||||
<font size="-1">
|
||||
<a href="mailto:jim_nance%yahoo.com">jim_nance@yahoo.com</a>
|
||||
<a href="mailto:jim_nance%yahoo.com">jim_nance@yahoo.com</a><p>
|
||||
Recent (4/2011) updates Randell Jesup (see bugzilla for contact info)
|
||||
</font>
|
||||
<hr>
|
||||
|
||||
@ -46,12 +47,26 @@ default pull. To do this do:
|
||||
<code>ac_add_options --enable-jprof</code> to your <code>.mozconfig</code>) and
|
||||
making sure that you do <strong>not</strong> have the
|
||||
<code>--enable-strip</code> configure option set -- jprof needs symbols to
|
||||
operate.</p>
|
||||
operate. On many architectures with GCC, you'll need to add
|
||||
<code>--enable-optimize="-O3 -fno-omit-frame-pointer"</code> or the
|
||||
equivalent to ensure frame pointer generation in the compiler you're using.</p>
|
||||
|
||||
<p>Finally, build mozilla with your new configuration. Now you can run jprof.</p>
|
||||
|
||||
<h3><a name="usage">Usage</a></h3>
|
||||
|
||||
Options:
|
||||
<ul>
|
||||
<li><b>-s depth</b> : Limit depth looked at from captured stack
|
||||
frames</li>
|
||||
<li><b>-v</b> : Output some information about the symbols, memory map, etc.</li>
|
||||
<li><b>-t</b> : Group output according to thread. Requires external
|
||||
LD_PRELOAD library to help force sampling of spawned threads; jprof
|
||||
normally captures the main thread only. See <a
|
||||
href="http://sam.zoy.org/writings/programming/gprof.html">gprof-helper</a>;
|
||||
it may need adaption for jprof.</li>
|
||||
<li><b>-e exclusion</b> : Allows excluding specific stack frames</li>
|
||||
<li><b>-i inclusion</b> : Allows including specific stack frames</li>
|
||||
</ul>
|
||||
The behavior of jprof is determined by the value of the JPROF_FLAGS environment
|
||||
variable. This environment variable can be composed of several substrings
|
||||
which have the following meanings:
|
||||
@ -67,7 +82,8 @@ which have the following meanings:
|
||||
<li> <b>JP_FIRST=x</b> : Wait x seconds before starting the timer
|
||||
|
||||
<li> <b>JP_PERIOD=y</b> : Set timer to interrupt every y seconds. Only
|
||||
values of y strictly greater than 0.001 are supported.
|
||||
values of y greater than or equal to 0.001 are supported. Default is
|
||||
0.050 (50ms).
|
||||
|
||||
<li> <b>JP_REALTIME</b> : Do the profiling in intervals of real time rather
|
||||
than intervals of time used by the mozilla process (and the kernel
|
||||
@ -103,10 +119,10 @@ being profiled
|
||||
<pre>
|
||||
setenv JPROF_FLAGS "JP_START JP_FIRST=3 JP_PERIOD=0.025" </pre>
|
||||
|
||||
<li>To make the timer start on your signal and fire every 1.5 milliseconds of
|
||||
<li>To make the timer start on your signal and fire every 1 millisecond of
|
||||
program time use:
|
||||
<pre>
|
||||
setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.0015" </pre>
|
||||
setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.001" </pre>
|
||||
|
||||
<li>To make the timer start on your signal and fire every 10 milliseconds of
|
||||
wall-clock time use:
|
||||
@ -189,82 +205,87 @@ corresponding to one function. A typical section looks something like
|
||||
this:
|
||||
|
||||
<blockquote><pre>
|
||||
<A href="#29355">141300 PL_ProcessPendingEvents</A>
|
||||
<A href="#29372"> 927 PL_ProcessEventsBeforeID</A>
|
||||
29358 0 <a name=29358> 142227</a> <b>PL_HandleEvent</b>
|
||||
<A href="#28546"> 92394 nsInputStreamReadyEvent::EventHandler(PLEvent*)</A>
|
||||
<A href="#41572"> 49181 HandlePLEvent(ReflowEvent*)</A>
|
||||
<A href="#29537"> 481 handleTimerEvent(TimerEventType*)</A>
|
||||
<A href="#34494"> 158 nsTransportStatusEvent::HandleEvent(PLEvent*)</A>
|
||||
<A href="#29359"> 9 PL_DestroyEvent</A>
|
||||
|
||||
<A href="#20319"> 4 __restore_rt</A>
|
||||
index Count Hits Function Name
|
||||
<A href="#72871"> 545 (46.4%) nsBlockFrame::ReflowInlineFrames(nsBlockReflowState&, nsLineList_iterator, int*)</A>
|
||||
<A href="#72873"> 100 (8.5%) nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&)</A>
|
||||
72870 4 (0.3%) <a name=72870> 645 (54.9%)</a> <b>nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, int*, LineReflowStatus*, int)</b>
|
||||
<A href="#72821"> 545 (46.4%) nsBlockFrame::ReflowInlineFrame(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*)</A>
|
||||
<A href="#72853"> 83 (7.1%) nsBlockFrame::PlaceLine(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFloatManager::SavedState*, nsRect&, int&, int*)</A>
|
||||
<A href="#74150"> 9 (0.8%) nsLineLayout::BeginLineReflow(int, int, int, int, int, int)</A>
|
||||
<A href="#74897"> 1 (0.1%) nsTextFrame::GetType() const</A>
|
||||
<A href="#74131"> 1 (0.1%) nsLineLayout::RelativePositionFrames(nsOverflowAreas&)</A>
|
||||
<A href="#58320"> 1 (0.1%) __i686.get_pc_thunk.bx</A>
|
||||
<A href="#53077"> 1 (0.1%) PL_ArenaAllocate</A>
|
||||
</pre></blockquote>
|
||||
|
||||
The information this block tells us is:
|
||||
|
||||
<ul>
|
||||
<li>There were 0 profiler hits <em>in</em> <code>PL_HandleEvent</code>
|
||||
<li>There were 142227 profiler hits <em>under</em> <code>PL_HandleEvent</code>. Of these:
|
||||
<li>There were 4 profiler hits <em>in</em> <code>nsBlockFrame::DoReflowInlineFrames</code>
|
||||
<li>There were 645 profiler hits <em>in or under</em> <code>nsBlockFrame::DoReflowInlineFrames</code>. Of these:
|
||||
<ul>
|
||||
<li>92394 were in or under <code>nsInputStreamReadyEvent::EventHandler</code>
|
||||
<li>49181 were in or under <code>HandlePLEvent(ReflowEvent*)</code>
|
||||
<li>481 were in or under <code>handleTimerEvent</code>
|
||||
<li>158 were in or under <code>nsTransportStatusEvent::HandleEvent</code>
|
||||
<li>9 were in or under <code>PL_DestroyEvent</code>
|
||||
<li>4 were in or under <code>__restore_rt</code>
|
||||
<li>545 were in or under <code>nsBlockFrame::ReflowInlineFrame</code>
|
||||
<li>83 were in or under <code>nsBlockFrame::PlaceLine</code>
|
||||
<li>9 were in or under <code>nsLineLayout::BeginLineReflow</code>
|
||||
<li>1 was in or under <code>nsTextFrame::GetType</code>
|
||||
<li>1 was in or under <code>nsLineLayout::RelativePositionFrames</code>
|
||||
<li>1 was in or under <code>__i686.get_pc_thunk.bx</code>
|
||||
<li>1 was in or under <code>PL_ArenaAllocate</code>
|
||||
</ul>
|
||||
<li>Of these 142227 calls into <code>PL_HandleEvent</code>:
|
||||
<li>Of these 645 calls into <code>nsBlockFrame::DoReflowInlineFrames</code>:
|
||||
<ul>
|
||||
<li>141300 came from <code>PL_ProcessPendingEvents</code>
|
||||
<li>927 came from <code>PL_ProcessEventsBeforeID</code>
|
||||
<li>545 came from <code>nsBlockFrame::ReflowInlineFrames</code>
|
||||
<li>100 came from <code>nsBlockFrame::ReflowDirtyLines</code>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
The rest of this section explains how to read this information off from the jprof output.
|
||||
|
||||
<p>This block corresponds to the function <code>PL_HandleEvent</code>, which is
|
||||
<p>This block corresponds to the function <code>nsBlockFrame::DoReflowInlineFrames</code>, which is
|
||||
therefore bolded and not a link. The name of this function is preceded by
|
||||
three numbers which have the following meaning. The number on the left (29358)
|
||||
is the index number, and is not important. The center number (0) is the number
|
||||
of times this function was interrupted by the timer. The last number (142227)
|
||||
is the number of times this function was in the call stack when the timer went
|
||||
five numbers which have the following meaning. The number on the left (72870)
|
||||
is the index number, and is not important. The next number (4) and the
|
||||
percentage following (0.3%) are the number
|
||||
of times this function was interrupted by the timer and the percentage of
|
||||
the total hits that is. The last number pair ("645 (54.9%)")
|
||||
are the number of times this function was in the call stack when the timer went
|
||||
off. That is, the timer went off while we were in code that was ultimately
|
||||
called from <code>PL_HandleEvent</code>.
|
||||
called from <code>nsBlockFrame::DoReflowInlineFrames</code>.
|
||||
<p>For our example we can see that our function was in the call stack for
|
||||
142227 interrupt ticks, but we were never the function that was running when
|
||||
the interrupt arrived.
|
||||
645 interrupt ticks, but we were only the function that was running when
|
||||
the interrupt arrived 4 times.
|
||||
<P>
|
||||
The functions listed above the line for <code>PL_HandleEvent</code> are its
|
||||
The functions listed above the line for <code>nsBlockFrame::DoReflowInlineFrames</code> are its
|
||||
callers. The numbers to the left of these function names are the numbers of
|
||||
times these functions were in the call stack as callers of
|
||||
<code>PL_HandleEvent</code>. In our example, we were called 927 times by
|
||||
<code>PL_ProcessEventsBeforeID</code> and 141300 times by
|
||||
<code>PL_ProcessPendingEvents</code>.
|
||||
<code>nsBlockFrame::DoReflowInlineFrames</code>. In our example, we were called 545 times by
|
||||
<code>nsBlockFrame::ReflowInlineFrames</code> and 100 times by
|
||||
<code>nsBlockFrame::ReflowDirtyLines</code>.
|
||||
<P>
|
||||
The functions listed below the line for <code>PL_HandleEvent</code> are its
|
||||
The functions listed below the line for <code>nsBlockFrame::DoReflowInlineFrames</code> are its
|
||||
callees. The numbers to the left of the function names are the numbers of
|
||||
times these functions were in the callstack as callees of <code>PL_HandleEvent</code>. In our example, of the 142227 profiler hits under <code>PL_HandleEvent</code> 92394 were under <code>nsInputStreamReadyEvent::EventHandler</code>, 49181 were under <code>HandlePLEvent(ReflowEvent*)</code>, and so forth.
|
||||
times these functions were in the callstack as callees of
|
||||
<code>nsBlockFrame::DoReflowInlineFrames</code> and the corresponding percentages. In our example, of the 645 profiler hits under <code>nsBlockFrame::DoReflowInlineFrames</code> 545 were under <code>nsBlockFrame::ReflowInlineFrame</code>, 83 were under <code>nsBlockFrame::PlaceLine</code>, and so forth.<p>
|
||||
|
||||
<b>NOTE:</b> If there are loops of execution or recursion, the numbers will
|
||||
not add up and percentages can exceed 100%. If a function directly calls
|
||||
itself "(self)" will be appended to the line, but indirect recursion will
|
||||
not be marked.
|
||||
|
||||
<h3>Bugs</h3>
|
||||
Jprof has only been tested under Red Hat Linux 6.0, 6.1, and 6.2. It does
|
||||
not work under 6.0, though it is possible hack up the source code and make
|
||||
it work there. The way I determine the stack trace from inside the
|
||||
signal handler is tightly bound to the version of glibc that is running.
|
||||
If you know of a more portable way to get this information please let
|
||||
me know.
|
||||
|
||||
<h3>Update</h3>
|
||||
The current build of Jprof has only been tested under Ubuntu 8.04 LTS, but
|
||||
should work under any fairly modern linux distribution using GCC/GLIBC.
|
||||
Please update this document with any known compatibilities/incompatibilities.
|
||||
<p>
|
||||
If you get an error:<p><code>Inconsistency detected by ld.so: dl-open.c: 260: dl_open_worker: Assertion `_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT' failed!
|
||||
</code><p>that means you've hit a timing hole in the version of glibc you're
|
||||
running. See <a
|
||||
href="http://sources.redhat.com/bugzilla/show_bug.cgi?id=4578">Redhat bug 4578</a>.
|
||||
<!-- <h3>Update</h3>
|
||||
<ul>
|
||||
<li>Ben Bucksch reports that installing the Red Hat 6.1 glibc rpms on a Red Hat
|
||||
6.0 system allows jprof to work, and does not seem to break anything except
|
||||
gdm (the Gnome login program), and that can be fixed by installing the RH 6.1
|
||||
gdb rpm.</li>
|
||||
<li>David Baron reports that jprof works under RedHat 6.0 if one uncomments
|
||||
the <code>#define JPROF_PTHREAD_HACK</code> near the beginning of
|
||||
<code>libmalloc.cpp</code>.</li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -128,6 +129,7 @@ leaky::leaky()
|
||||
|
||||
quiet = TRUE;
|
||||
showAddress = FALSE;
|
||||
showThreads = FALSE;
|
||||
stackDepth = 100000;
|
||||
|
||||
mappedLogFile = -1;
|
||||
@ -149,7 +151,8 @@ leaky::~leaky()
|
||||
|
||||
void leaky::usageError()
|
||||
{
|
||||
fprintf(stderr, "Usage: %s prog log\n", (char*) applicationName);
|
||||
fprintf(stderr, "Usage: %s [-v][-t] [-e exclude] [-i include] [-s stackdepth] prog log\n", (char*) applicationName);
|
||||
fprintf(stderr, "\t-v: verbose\n\t-t: split threads\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -165,14 +168,15 @@ void leaky::initialize(int argc, char** argv)
|
||||
|
||||
int arg;
|
||||
int errflg = 0;
|
||||
while ((arg = getopt(argc, argv, "adEe:gh:i:r:Rs:tqx")) != -1) {
|
||||
while ((arg = getopt(argc, argv, "adEe:gh:i:r:Rs:tqvx")) != -1) {
|
||||
switch (arg) {
|
||||
case '?':
|
||||
default:
|
||||
errflg++;
|
||||
break;
|
||||
case 'a':
|
||||
break;
|
||||
case 'A':
|
||||
case 'A': // not implemented
|
||||
showAddress = TRUE;
|
||||
break;
|
||||
case 'd':
|
||||
@ -184,7 +188,7 @@ void leaky::initialize(int argc, char** argv)
|
||||
break;
|
||||
case 'g':
|
||||
break;
|
||||
case 'r':
|
||||
case 'r': // not implemented
|
||||
roots.add(optarg);
|
||||
if (!includes.IsEmpty()) {
|
||||
errflg++;
|
||||
@ -207,7 +211,12 @@ void leaky::initialize(int argc, char** argv)
|
||||
case 'x':
|
||||
break;
|
||||
case 'q':
|
||||
quiet = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
quiet = !quiet;
|
||||
break;
|
||||
case 't':
|
||||
showThreads = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -265,6 +274,10 @@ void leaky::LoadMap()
|
||||
|
||||
void leaky::open()
|
||||
{
|
||||
int threadArray[100]; // should auto-expand
|
||||
int last_thread = -1;
|
||||
int numThreads=0;
|
||||
|
||||
LoadMap();
|
||||
|
||||
setupSymbols(progFile);
|
||||
@ -279,7 +292,61 @@ void leaky::open()
|
||||
firstLogEntry = (malloc_log_entry*) mapFile(mappedLogFile, PROT_READ, &size);
|
||||
lastLogEntry = (malloc_log_entry*)((char*)firstLogEntry + size);
|
||||
|
||||
analyze();
|
||||
fprintf(stdout,"<html><head><title>Jprof Profile Report</title></head><body>\n");
|
||||
fprintf(stdout,"<h1><center>Jprof Profile Report</center></h1>\n");
|
||||
|
||||
if (showThreads)
|
||||
{
|
||||
// Find all the threads captured
|
||||
|
||||
// pthread/linux docs say the signal can be delivered to any thread in
|
||||
// the process. In practice, it appears in Linux that it's always
|
||||
// delivered to the thread that called setitimer(), and each thread can
|
||||
// have a separate itimer. There's a support library for gprof that
|
||||
// overlays pthread_create() to set timers in any threads you spawn.
|
||||
|
||||
// This loop walks through all the call stacks we recorded
|
||||
for (malloc_log_entry* lep=firstLogEntry;
|
||||
lep < lastLogEntry;
|
||||
lep = reinterpret_cast<malloc_log_entry*>(&lep->pcs[lep->numpcs])) {
|
||||
if (lep->thread != last_thread)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<numThreads; i++)
|
||||
{
|
||||
if (lep->thread == threadArray[i])
|
||||
break;
|
||||
}
|
||||
if (i == numThreads &&
|
||||
i < (int) (sizeof(threadArray)/sizeof(threadArray[0])))
|
||||
{
|
||||
threadArray[i] = lep->thread;
|
||||
numThreads++;
|
||||
fprintf(stderr,"new thread %d\n",lep->thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"Num threads %d\n",numThreads);
|
||||
|
||||
fprintf(stdout,"<hr>Threads:<p><pre>\n");
|
||||
for (int i=0; i<numThreads; i++)
|
||||
{
|
||||
fprintf(stdout," <a href=\"thread_%d\">%d</a><p>\n",
|
||||
threadArray[i],threadArray[i]);
|
||||
}
|
||||
fprintf(stdout,"</pre><hr>");
|
||||
|
||||
for (int i=0; i<numThreads; i++)
|
||||
{
|
||||
analyze(threadArray[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
analyze(0);
|
||||
}
|
||||
|
||||
fprintf(stdout,"</pre></body></html>\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@ -428,14 +495,19 @@ void leaky::dumpEntryToLog(malloc_log_entry* lep)
|
||||
displayStackTrace(stdout, lep);
|
||||
}
|
||||
|
||||
void leaky::generateReportHTML(FILE *fp, int *countArray, int count)
|
||||
void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
|
||||
{
|
||||
fprintf(fp,"<html><head><title>Jprof Profile Report</title></head><body>\n");
|
||||
fprintf(fp,"<h1><center>Jprof Profile Report</center></h1>\n");
|
||||
fprintf(fp,"<center>");
|
||||
fprintf(fp,"<A href=#flat>flat</A><b> | </b><A href=#hier>hierarchical</A>");
|
||||
if (showThreads)
|
||||
{
|
||||
fprintf(fp,"<hr><A NAME=thread_%d><b>Thread: %d</b></A><p>",
|
||||
thread,thread);
|
||||
}
|
||||
fprintf(fp,"<A href=#flat_%d>flat</A><b> | </b><A href=#hier_%d>hierarchical</A>",
|
||||
thread,thread);
|
||||
fprintf(fp,"</center><P><P><P>\n");
|
||||
|
||||
int totalTimerHits = count;
|
||||
int *rankingTable = new int[usefulSymbols];
|
||||
|
||||
for(int cnt=usefulSymbols; --cnt>=0; rankingTable[cnt]=cnt);
|
||||
@ -464,23 +536,29 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count)
|
||||
// this loop. Later we can get callers and callees into it like gprof
|
||||
// does
|
||||
fprintf(fp,
|
||||
"<h2><A NAME=hier></A><center><a href=\"http://lxr.mozilla.org/mozilla/source/tools/jprof/README.html#hier\">Hierarchical Profile</a></center></h2><hr>\n");
|
||||
"<h2><A NAME=hier_%d></A><center><a href=\"http://lxr.mozilla.org/mozilla/source/tools/jprof/README.html#hier\">Hierarchical Profile</a></center></h2><hr>\n",
|
||||
thread);
|
||||
fprintf(fp, "<pre>\n");
|
||||
fprintf(fp, "%5s %5s %4s %s\n",
|
||||
"index", "Count", "Hits", "Function Name");
|
||||
fprintf(fp, "%6s %6s %4s %s\n",
|
||||
"index", "Count", "Hits", "Function Name");
|
||||
|
||||
for(i=0; i<usefulSymbols && countArray[rankingTable[i]]>0; i++) {
|
||||
Symbol *sp=&externalSymbols[rankingTable[i]];
|
||||
|
||||
sp->cntP.printReport(fp, this);
|
||||
sp->cntP.printReport(fp, this, rankingTable[i], totalTimerHits);
|
||||
|
||||
char *symname = htmlify(sp->name);
|
||||
fprintf(fp, "%6d %3d <a name=%d>%8d</a> <b>%s</b>\n", rankingTable[i],
|
||||
sp->timerHit, rankingTable[i], countArray[rankingTable[i]],
|
||||
fprintf(fp, "%6d %6d (%3.1f%%)%s <a name=%d>%8d (%3.1f%%)</a>%s <b>%s</b>\n",
|
||||
rankingTable[i],
|
||||
sp->timerHit, (sp->timerHit*1000/totalTimerHits)/10.0,
|
||||
(sp->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
|
||||
rankingTable[i], countArray[rankingTable[i]],
|
||||
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0,
|
||||
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
|
||||
symname);
|
||||
delete [] symname;
|
||||
|
||||
sp->cntC.printReport(fp, this);
|
||||
sp->cntC.printReport(fp, this, rankingTable[i], totalTimerHits);
|
||||
|
||||
fprintf(fp, "<hr>\n");
|
||||
}
|
||||
@ -508,14 +586,21 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count)
|
||||
// I wanted the total before walking the list, if this
|
||||
// double-pass over externalSymbols gets slow we can
|
||||
// do single-pass and print this out after the loop finishes.
|
||||
int totalTimerHits = 0;
|
||||
totalTimerHits = 0;
|
||||
for(i=0;
|
||||
i<usefulSymbols && externalSymbols[rankingTable[i]].timerHit>0; i++) {
|
||||
Symbol *sp=&externalSymbols[rankingTable[i]];
|
||||
totalTimerHits += sp->timerHit;
|
||||
}
|
||||
if (totalTimerHits == 0)
|
||||
totalTimerHits = 1;
|
||||
|
||||
fprintf(fp,"<h2><A NAME=flat></A><center><a href=\"http://lxr.mozilla.org/mozilla/source/tools/jprof/README.html#flat\">Flat Profile</a></center></h2><br>\n");
|
||||
if (totalTimerHits != count)
|
||||
fprintf(stderr,"Hit count mismatch: count=%d; totalTimerHits=%d",
|
||||
count,totalTimerHits);
|
||||
|
||||
fprintf(fp,"<h2><A NAME=flat_%d></A><center><a href=\"http://lxr.mozilla.org/mozilla/source/tools/jprof/README.html#flat\">Flat Profile</a></center></h2><br>\n",
|
||||
thread);
|
||||
fprintf(fp, "<pre>\n");
|
||||
|
||||
fprintf(fp, "Total hit count: %d\n", totalTimerHits);
|
||||
@ -532,11 +617,9 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count)
|
||||
((float)sp->timerHit/(float)totalTimerHits)*100.0, symname);
|
||||
delete [] symname;
|
||||
}
|
||||
|
||||
fprintf(fp,"</pre></body></html>\n");
|
||||
}
|
||||
|
||||
void leaky::analyze()
|
||||
void leaky::analyze(int thread)
|
||||
{
|
||||
int *countArray = new int[usefulSymbols];
|
||||
int *flagArray = new int[usefulSymbols];
|
||||
@ -558,8 +641,11 @@ void leaky::analyze()
|
||||
lep < lastLogEntry;
|
||||
lep = reinterpret_cast<malloc_log_entry*>(&lep->pcs[lep->numpcs])) {
|
||||
|
||||
if (excluded(lep) || !included(lep))
|
||||
if ((thread != 0 && lep->thread != thread) ||
|
||||
excluded(lep) || !included(lep))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++stacks; // How many stack frames did we collect
|
||||
|
||||
@ -568,7 +654,7 @@ void leaky::analyze()
|
||||
u_int n = (lep->numpcs < stackDepth) ? lep->numpcs : stackDepth;
|
||||
char** pcp = &lep->pcs[n-1];
|
||||
int idx=-1, parrentIdx=-1; // Init idx incase n==0
|
||||
for(int i=n-1; i>=0; --i, --pcp, parrentIdx=idx) {
|
||||
for (int i=n-1; i>=0; --i, --pcp) {
|
||||
idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp));
|
||||
|
||||
if(idx>=0) {
|
||||
@ -593,6 +679,9 @@ void leaky::analyze()
|
||||
externalSymbols[parrentIdx].regChild(idx);
|
||||
externalSymbols[idx].regParrent(parrentIdx);
|
||||
}
|
||||
// inside if() so an unknown in the middle of a stack won't break
|
||||
// the link!
|
||||
parrentIdx=idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,12 +691,12 @@ void leaky::analyze()
|
||||
}
|
||||
}
|
||||
|
||||
generateReportHTML(stdout, countArray, stacks);
|
||||
generateReportHTML(stdout, countArray, stacks, thread);
|
||||
}
|
||||
|
||||
void FunctionCount::printReport(FILE *fp, leaky *lk)
|
||||
void FunctionCount::printReport(FILE *fp, leaky *lk, int parent, int total)
|
||||
{
|
||||
const char *fmt = " <A href=\"#%d\">%6d %s</A>\n";
|
||||
const char *fmt = " <A href=\"#%d\">%8d (%3.1f%%)%s %s</A>%s\n";
|
||||
|
||||
int nmax, tmax=((~0U)>>1);
|
||||
|
||||
@ -618,7 +707,11 @@ void FunctionCount::printReport(FILE *fp, leaky *lk)
|
||||
if(cnt==tmax) {
|
||||
int idx = getIndex(j);
|
||||
char *symname = htmlify(lk->indexToName(idx));
|
||||
fprintf(fp, fmt, idx, getCount(j), symname);
|
||||
fprintf(fp, fmt, idx, getCount(j),
|
||||
getCount(j)*100.0/total,
|
||||
getCount(j)*100.0/total >= 10.0 ? "" : " ",
|
||||
symname,
|
||||
parent == idx ? " (self)" : "");
|
||||
delete [] symname;
|
||||
} else if(cnt<tmax && cnt>nmax) {
|
||||
nmax=cnt;
|
||||
|
@ -52,7 +52,7 @@ struct leaky;
|
||||
class FunctionCount : public IntCount
|
||||
{
|
||||
public:
|
||||
void printReport(FILE *fp, leaky *lk);
|
||||
void printReport(FILE *fp, leaky *lk, int parent, int total);
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
@ -90,6 +90,7 @@ struct leaky {
|
||||
|
||||
int quiet;
|
||||
int showAddress;
|
||||
int showThreads;
|
||||
u_int stackDepth;
|
||||
|
||||
int mappedLogFile;
|
||||
@ -115,7 +116,7 @@ struct leaky {
|
||||
|
||||
void LoadMap();
|
||||
|
||||
void analyze();
|
||||
void analyze(int thread);
|
||||
|
||||
void dumpEntryToLog(malloc_log_entry* lep);
|
||||
|
||||
@ -133,7 +134,7 @@ struct leaky {
|
||||
const char* indexToName(int idx) {return externalSymbols[idx].name;}
|
||||
|
||||
private:
|
||||
void generateReportHTML(FILE *fp, int *countArray, int count);
|
||||
void generateReportHTML(FILE *fp, int *countArray, int count, int thread);
|
||||
int findSymbolIndex(u_long address);
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,9 @@ EXPORTS =
|
||||
LIBRARY_NAME = jprof
|
||||
EXPORT_LIBRARY = 1
|
||||
|
||||
# override optimization
|
||||
MOZ_OPTIMIZE_FLAGS = -fno-omit-frame-pointer
|
||||
|
||||
CPPSRCS = \
|
||||
libmalloc.cpp \
|
||||
$(NULL)
|
||||
|
@ -23,6 +23,7 @@
|
||||
* Jim Nance
|
||||
* L. David Baron - JP_REALTIME, JPROF_PTHREAD_HACK, and SIGUSR1 handling
|
||||
* Mike Shaver - JP_RTC_HZ support
|
||||
* Randell Jesup - glibc backtrace() support
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -61,7 +62,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <ucontext.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
#include "libmalloc.h"
|
||||
#include "jprof.h"
|
||||
@ -77,6 +80,10 @@ extern r_debug _r_debug;
|
||||
#include <link.h>
|
||||
#endif
|
||||
|
||||
#define USE_GLIBC_BACKTRACE 1
|
||||
// To debug, use #define JPROF_STATIC
|
||||
#define JPROF_STATIC //static
|
||||
|
||||
static int gLogFD = -1;
|
||||
static pthread_t main_thread;
|
||||
|
||||
@ -87,9 +94,32 @@ static int enableRTCSignals(bool enable);
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if defined(i386) || defined(_i386) || defined(__x86_64__)
|
||||
static void CrawlStack(malloc_log_entry* me,
|
||||
void* stack_top, void* top_instr_ptr)
|
||||
JPROF_STATIC void CrawlStack(malloc_log_entry* me,
|
||||
void* stack_top, void* top_instr_ptr)
|
||||
{
|
||||
#if USE_GLIBC_BACKTRACE
|
||||
// This probably works on more than x86! But we need a way to get the
|
||||
// top instruction pointer, which is kindof arch-specific
|
||||
void *array[500];
|
||||
int cnt, i;
|
||||
u_long numpcs = 0;
|
||||
bool tracing = false;
|
||||
|
||||
// This is from glibc. A more generic version might use
|
||||
// libunwind and/or CaptureStackBackTrace() on Windows
|
||||
cnt = backtrace(&array[0],sizeof(array)/sizeof(array[0]));
|
||||
|
||||
// StackHook->JprofLog->CrawlStack
|
||||
// Then we have sigaction, which replaced top_instr_ptr
|
||||
array[3] = top_instr_ptr;
|
||||
for (i = 3; i < cnt; i++)
|
||||
{
|
||||
me->pcs[numpcs++] = (char *) array[i];
|
||||
}
|
||||
me->numpcs = numpcs;
|
||||
|
||||
#else
|
||||
// original code - this breaks on many platforms
|
||||
void **bp;
|
||||
#if defined(__i386)
|
||||
__asm__( "movl %%ebp, %0" : "=g"(bp));
|
||||
@ -102,6 +132,7 @@ static void CrawlStack(malloc_log_entry* me,
|
||||
bp = __builtin_frame_address(0);
|
||||
#endif
|
||||
u_long numpcs = 0;
|
||||
bool tracing = false;
|
||||
|
||||
me->pcs[numpcs++] = (char*) top_instr_ptr;
|
||||
|
||||
@ -111,13 +142,17 @@ static void CrawlStack(malloc_log_entry* me,
|
||||
if (nextbp < bp) {
|
||||
break;
|
||||
}
|
||||
if (bp > stack_top) {
|
||||
if (tracing) {
|
||||
// Skip the signal handling.
|
||||
me->pcs[numpcs++] = (char*) pc;
|
||||
}
|
||||
else if (pc == top_instr_ptr) {
|
||||
tracing = true;
|
||||
}
|
||||
bp = nextbp;
|
||||
}
|
||||
me->numpcs = numpcs;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -169,13 +204,14 @@ static void EndProfilingHook(int signum)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
Log(u_long aTime, void* stack_top, void* top_instr_ptr)
|
||||
JPROF_STATIC void
|
||||
JprofLog(u_long aTime, void* stack_top, void* top_instr_ptr)
|
||||
{
|
||||
// Static is simply to make debugging tollerable
|
||||
static malloc_log_entry me;
|
||||
|
||||
me.delTime = aTime;
|
||||
me.thread = syscall(SYS_gettid); //gettid();
|
||||
|
||||
CrawlStack(&me, stack_top, top_instr_ptr);
|
||||
|
||||
@ -281,7 +317,7 @@ static int enableRTCSignals(bool enable)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void StackHook(
|
||||
JPROF_STATIC void StackHook(
|
||||
int signum,
|
||||
siginfo_t *info,
|
||||
void *ucontext)
|
||||
@ -325,9 +361,9 @@ void *ucontext)
|
||||
|
||||
gregset_t &gregs = ((ucontext_t*)ucontext)->uc_mcontext.gregs;
|
||||
#ifdef __x86_64__
|
||||
Log(millisec, (void*)gregs[REG_RSP], (void*)gregs[REG_RIP]);
|
||||
JprofLog(millisec, (void*)gregs[REG_RSP], (void*)gregs[REG_RIP]);
|
||||
#else
|
||||
Log(millisec, (void*)gregs[REG_ESP], (void*)gregs[REG_EIP]);
|
||||
JprofLog(millisec, (void*)gregs[REG_ESP], (void*)gregs[REG_EIP]);
|
||||
#endif
|
||||
|
||||
if (!rtcHz)
|
||||
@ -371,21 +407,26 @@ NS_EXPORT_(void) setupProfilingStuff(void)
|
||||
|
||||
char *delay = strstr(tst,"JP_PERIOD=");
|
||||
if(delay) {
|
||||
double tmp = strtod(delay+10, NULL);
|
||||
if(tmp>1e-3) {
|
||||
double tmp = strtod(delay+strlen("JP_PERIOD="), NULL);
|
||||
if (tmp>=1e-3) {
|
||||
timerMiliSec = static_cast<unsigned long>(1000 * tmp);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n",
|
||||
tmp);
|
||||
timerMiliSec = 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *first = strstr(tst, "JP_FIRST=");
|
||||
if(first) {
|
||||
firstDelay = atol(first+9);
|
||||
firstDelay = atol(first+strlen("JP_FIRST="));
|
||||
}
|
||||
|
||||
char *rtc = strstr(tst, "JP_RTC_HZ=");
|
||||
if (rtc) {
|
||||
#if defined(linux)
|
||||
rtcHz = atol(rtc+10);
|
||||
rtcHz = atol(rtc+strlen("JP_RTC_HZ="));
|
||||
timerMiliSec = 0; /* This makes JP_FIRST work right. */
|
||||
realTime = 1; /* It's the _R_TC and all. ;) */
|
||||
|
||||
@ -420,6 +461,8 @@ NS_EXPORT_(void) setupProfilingStuff(void)
|
||||
atexit(DumpAddressMap);
|
||||
|
||||
main_thread = pthread_self();
|
||||
//fprintf(stderr,"jprof: main_thread = %u\n",
|
||||
// (unsigned int)main_thread);
|
||||
|
||||
sigemptyset(&mset);
|
||||
action.sa_handler = NULL;
|
||||
|
@ -52,6 +52,7 @@ typedef unsigned long u_long;
|
||||
struct malloc_log_entry {
|
||||
u_long delTime;
|
||||
u_long numpcs;
|
||||
int thread;
|
||||
char* pcs[MAX_STACK_CRAWL];
|
||||
};
|
||||
|
||||
|
@ -415,6 +415,12 @@ class nsHashKey;
|
||||
// Query if the DOM element under nsEvent::refPoint belongs to our widget
|
||||
// or not.
|
||||
#define NS_QUERY_DOM_WIDGET_HITTEST (NS_QUERY_CONTENT_EVENT_START + 9)
|
||||
// Query for some information about mouse wheel event's target
|
||||
// XXX This is used only for supporting high resolution mouse scroll on Windows
|
||||
// and it's going to be reimplemented with another approach. At that time,
|
||||
// this even is going to be removed. Therefore, DON'T use this event for
|
||||
// other purpose.
|
||||
#define NS_QUERY_SCROLL_TARGET_INFO (NS_QUERY_CONTENT_EVENT_START + 99)
|
||||
|
||||
// Video events
|
||||
#ifdef MOZ_MEDIA
|
||||
@ -1188,9 +1194,11 @@ public:
|
||||
// as needed.
|
||||
kNoDefer = 1 << 5, // For scrollable views, indicates scroll should not
|
||||
// occur asynchronously.
|
||||
kIsMomentum = 1 << 6 // Marks scroll events that aren't controlled by the
|
||||
kIsMomentum = 1 << 6, // Marks scroll events that aren't controlled by the
|
||||
// user but fire automatically as the result of a
|
||||
// "momentum" scroll.
|
||||
kAllowSmoothScroll = 1 << 7 // Allow smooth scroll for the pixel scroll
|
||||
// event.
|
||||
};
|
||||
|
||||
nsMouseScrollEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
|
||||
@ -1285,6 +1293,13 @@ public:
|
||||
refPoint = aPoint;
|
||||
}
|
||||
|
||||
void InitForQueryScrollTargetInfo(nsMouseScrollEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(message == NS_QUERY_SCROLL_TARGET_INFO,
|
||||
"wrong initializer is called");
|
||||
mInput.mMouseScrollEvent = aEvent;
|
||||
}
|
||||
|
||||
PRUint32 GetSelectionStart(void) const
|
||||
{
|
||||
NS_ASSERTION(message == NS_QUERY_SELECTED_TEXT,
|
||||
@ -1304,6 +1319,8 @@ public:
|
||||
struct {
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mLength;
|
||||
// used by NS_QUERY_SCROLL_TARGET_INFO
|
||||
nsMouseScrollEvent* mMouseScrollEvent;
|
||||
} mInput;
|
||||
struct {
|
||||
void* mContentsRoot;
|
||||
@ -1317,6 +1334,10 @@ public:
|
||||
PRPackedBool mWidgetIsHit; // true if DOM element under mouse belongs to widget
|
||||
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
|
||||
nsCOMPtr<nsITransferable> mTransferable;
|
||||
// used by NS_QUERY_SCROLL_TARGET_INFO
|
||||
PRInt32 mLineHeight;
|
||||
PRInt32 mPageWidth;
|
||||
PRInt32 mPageHeight;
|
||||
} mReply;
|
||||
|
||||
enum {
|
||||
@ -1620,15 +1641,7 @@ enum nsDragDropEventStatus {
|
||||
((evnt)->message == NS_PLUGIN_FOCUS))
|
||||
|
||||
#define NS_IS_QUERY_CONTENT_EVENT(evnt) \
|
||||
(((evnt)->message == NS_QUERY_SELECTED_TEXT) || \
|
||||
((evnt)->message == NS_QUERY_TEXT_CONTENT) || \
|
||||
((evnt)->message == NS_QUERY_CARET_RECT) || \
|
||||
((evnt)->message == NS_QUERY_TEXT_RECT) || \
|
||||
((evnt)->message == NS_QUERY_EDITOR_RECT) || \
|
||||
((evnt)->message == NS_QUERY_CONTENT_STATE) || \
|
||||
((evnt)->message == NS_QUERY_SELECTION_AS_TRANSFERABLE) || \
|
||||
((evnt)->message == NS_QUERY_CHARACTER_AT_POINT) || \
|
||||
((evnt)->message == NS_QUERY_DOM_WIDGET_HITTEST))
|
||||
((evnt)->eventStructType == NS_QUERY_CONTENT_EVENT)
|
||||
|
||||
#define NS_IS_SELECTION_EVENT(evnt) \
|
||||
(((evnt)->message == NS_SELECTION_SET))
|
||||
@ -1670,7 +1683,8 @@ enum nsDragDropEventStatus {
|
||||
// cases, you should use NS_IS_IME_RELATED_EVENT instead.
|
||||
#define NS_IS_IME_RELATED_EVENT(evnt) \
|
||||
(NS_IS_IME_EVENT(evnt) || \
|
||||
NS_IS_QUERY_CONTENT_EVENT(evnt) || \
|
||||
(NS_IS_QUERY_CONTENT_EVENT(evnt) && \
|
||||
evnt->message != NS_QUERY_SCROLL_TARGET_INFO) || \
|
||||
NS_IS_SELECTION_EVENT(evnt))
|
||||
|
||||
/*
|
||||
|
@ -109,6 +109,50 @@ struct ParamTraits<nsInputEvent>
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsMouseEvent_base>
|
||||
{
|
||||
typedef nsMouseEvent_base paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, static_cast<nsInputEvent>(aParam));
|
||||
WriteParam(aMsg, aParam.button);
|
||||
WriteParam(aMsg, aParam.pressure);
|
||||
WriteParam(aMsg, aParam.inputSource);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, static_cast<nsInputEvent*>(aResult)) &&
|
||||
ReadParam(aMsg, aIter, &aResult->button) &&
|
||||
ReadParam(aMsg, aIter, &aResult->pressure) &&
|
||||
ReadParam(aMsg, aIter, &aResult->inputSource);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsMouseScrollEvent>
|
||||
{
|
||||
typedef nsMouseScrollEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, static_cast<nsMouseEvent_base>(aParam));
|
||||
WriteParam(aMsg, aParam.scrollFlags);
|
||||
WriteParam(aMsg, aParam.delta);
|
||||
WriteParam(aMsg, aParam.scrollOverflow);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, static_cast<nsMouseEvent_base*>(aResult)) &&
|
||||
ReadParam(aMsg, aIter, &aResult->scrollFlags) &&
|
||||
ReadParam(aMsg, aIter, &aResult->delta) &&
|
||||
ReadParam(aMsg, aIter, &aResult->scrollOverflow);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsTextRangeStyle>
|
||||
{
|
||||
@ -235,12 +279,16 @@ struct ParamTraits<nsQueryContentEvent>
|
||||
WriteParam(aMsg, aParam.mSucceeded);
|
||||
WriteParam(aMsg, aParam.mInput.mOffset);
|
||||
WriteParam(aMsg, aParam.mInput.mLength);
|
||||
WriteParam(aMsg, *aParam.mInput.mMouseScrollEvent);
|
||||
WriteParam(aMsg, aParam.mReply.mOffset);
|
||||
WriteParam(aMsg, aParam.mReply.mString);
|
||||
WriteParam(aMsg, aParam.mReply.mRect);
|
||||
WriteParam(aMsg, aParam.mReply.mReversed);
|
||||
WriteParam(aMsg, aParam.mReply.mHasSelection);
|
||||
WriteParam(aMsg, aParam.mReply.mWidgetIsHit);
|
||||
WriteParam(aMsg, aParam.mReply.mLineHeight);
|
||||
WriteParam(aMsg, aParam.mReply.mPageHeight);
|
||||
WriteParam(aMsg, aParam.mReply.mPageWidth);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
@ -250,12 +298,16 @@ struct ParamTraits<nsQueryContentEvent>
|
||||
ReadParam(aMsg, aIter, &aResult->mSucceeded) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInput.mOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInput.mLength) &&
|
||||
ReadParam(aMsg, aIter, aResult->mInput.mMouseScrollEvent) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mString) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mReversed) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mHasSelection) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit);
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mLineHeight) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mPageHeight) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mPageWidth);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1137,40 +1137,82 @@ nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
static const CellRenderSettings progressSettings[2] = {
|
||||
// Determined settings.
|
||||
static const CellRenderSettings progressSettings[2][2] = {
|
||||
// Vertical progress bar.
|
||||
{
|
||||
// Determined settings.
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(0, 10), // small
|
||||
NSMakeSize(0, 16) // regular
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(10, 0), // small
|
||||
NSMakeSize(16, 0) // regular
|
||||
},
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{1, 1, 1, 1} // regular
|
||||
}
|
||||
}
|
||||
},
|
||||
// There is no horizontal margin in regular undetermined size.
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{1, 1, 1, 1} // regular
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(10, 0), // small
|
||||
NSMakeSize(16, 0) // regular
|
||||
},
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{1, 0, 1, 0} // regular
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// There is no horizontal margin in regular undetermined size.
|
||||
// Horizontal progress bar.
|
||||
{
|
||||
// Determined settings.
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(0, 10), // small
|
||||
NSMakeSize(0, 16) // regular
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(0, 10), // small
|
||||
NSMakeSize(0, 16) // regular
|
||||
},
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{1, 1, 1, 1} // regular
|
||||
}
|
||||
}
|
||||
},
|
||||
// There is no horizontal margin in regular undetermined size.
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{0, 1, 0, 1} // regular
|
||||
{
|
||||
NSZeroSize, // mini
|
||||
NSMakeSize(0, 10), // small
|
||||
NSMakeSize(0, 16) // regular
|
||||
},
|
||||
{
|
||||
NSZeroSize, NSZeroSize, NSZeroSize
|
||||
},
|
||||
{
|
||||
{ // Leopard
|
||||
{0, 0, 0, 0}, // mini
|
||||
{1, 1, 1, 1}, // small
|
||||
{0, 1, 0, 1} // regular
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1194,7 +1236,7 @@ nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect
|
||||
: NSClearControlTint)];
|
||||
|
||||
DrawCellWithSnapping(cell, cgContext, inBoxRect,
|
||||
progressSettings[inIsIndeterminate],
|
||||
progressSettings[inIsHorizontal][inIsIndeterminate],
|
||||
VerticalAlignFactor(aFrame), mCellDrawView,
|
||||
IsFrameRTL(aFrame));
|
||||
|
||||
@ -1895,8 +1937,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
|
||||
NS_WARNING("Unable to animate progressbar!");
|
||||
}
|
||||
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame, eventState),
|
||||
PR_TRUE, GetProgressValue(aFrame),
|
||||
GetProgressMaxValue(aFrame), aFrame);
|
||||
aFrame->GetStyleDisplay()->mOrient != NS_STYLE_ORIENT_VERTICAL,
|
||||
GetProgressValue(aFrame), GetProgressMaxValue(aFrame), aFrame);
|
||||
break;
|
||||
|
||||
case NS_THEME_PROGRESSBAR_VERTICAL:
|
||||
|
@ -2248,28 +2248,38 @@ moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
||||
|
||||
TSOffsetStyleGCs(style, rect->x, rect->y);
|
||||
|
||||
if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE) {
|
||||
if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
|
||||
widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
|
||||
/**
|
||||
* The bar's width and the bar speed are set depending of the progress
|
||||
* bar size. These could also be constant for all progress bars easily.
|
||||
* The bar's size and the bar speed are set depending of the progress'
|
||||
* size. These could also be constant for all progress bars easily.
|
||||
*/
|
||||
gboolean vertical = (widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE);
|
||||
|
||||
/* The size of the dimension we are going to use for the animation. */
|
||||
const gint progressSize = vertical ? rect->height : rect->width;
|
||||
|
||||
/* The bar is using a fifth of the element size, based on GtkProgressBar
|
||||
* activity-blocks property. */
|
||||
const gint barWidth = MAX(1, rect->width / 5);
|
||||
const gint barSize = MAX(1, progressSize / 5);
|
||||
|
||||
/* Represents the travel that has to be done for a complete cycle. */
|
||||
const gint travel = 2 * (rect->width - barWidth);
|
||||
const gint travel = 2 * (progressSize - barSize);
|
||||
|
||||
/* period equals to travel / pixelsPerMillisecond
|
||||
* where pixelsPerMillisecond equals rect->width / 1000.0.
|
||||
* where pixelsPerMillisecond equals progressSize / 1000.0.
|
||||
* This is equivalent to 1600. */
|
||||
const guint period = 1600;
|
||||
static const guint period = 1600;
|
||||
const gint t = PR_IntervalToMilliseconds(PR_IntervalNow()) % period;
|
||||
const gint dx = travel * t / period;
|
||||
|
||||
rect->x += (dx < travel / 2) ? dx : travel - dx;
|
||||
rect->width = barWidth;
|
||||
if (vertical) {
|
||||
rect->y += (dx < travel / 2) ? dx : travel - dx;
|
||||
rect->height = barSize;
|
||||
} else {
|
||||
rect->x += (dx < travel / 2) ? dx : travel - dx;
|
||||
rect->width = barSize;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
|
||||
@ -2986,6 +2996,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
|
||||
case MOZ_GTK_GRIPPER:
|
||||
case MOZ_GTK_PROGRESS_CHUNK:
|
||||
case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
|
||||
case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
|
||||
case MOZ_GTK_EXPANDER:
|
||||
case MOZ_GTK_TREEVIEW_EXPANDER:
|
||||
case MOZ_GTK_TOOLBAR_SEPARATOR:
|
||||
@ -3333,6 +3344,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
|
||||
break;
|
||||
case MOZ_GTK_PROGRESS_CHUNK:
|
||||
case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
|
||||
case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
|
||||
return moz_gtk_progress_chunk_paint(drawable, rect, cliprect,
|
||||
direction, widget);
|
||||
break;
|
||||
|
@ -180,6 +180,8 @@ typedef enum {
|
||||
MOZ_GTK_PROGRESS_CHUNK,
|
||||
/* Paints a progress chunk of an indeterminated GtkProgressBar. */
|
||||
MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE,
|
||||
/* Paints a progress chunk of a vertical indeterminated GtkProgressBar. */
|
||||
MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE,
|
||||
/* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
|
||||
MOZ_GTK_TAB,
|
||||
/* Paints the background and border of a GtkNotebook. */
|
||||
|
@ -571,7 +571,9 @@ nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
|
||||
nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
|
||||
|
||||
aGtkWidgetType = IsIndeterminateProgress(stateFrame, eventStates)
|
||||
? MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
|
||||
? (stateFrame->GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL)
|
||||
? MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
|
||||
: MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
|
||||
: MOZ_GTK_PROGRESS_CHUNK;
|
||||
}
|
||||
break;
|
||||
@ -881,7 +883,8 @@ nsNativeThemeGTK::DrawWidgetBackground(nsRenderingContext* aContext,
|
||||
}
|
||||
|
||||
// Indeterminate progress bar are animated.
|
||||
if (gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE) {
|
||||
if (gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
|
||||
gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
|
||||
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
|
||||
NS_WARNING("unable to animate widget!");
|
||||
}
|
||||
|
@ -298,6 +298,18 @@ PRUint32 nsWindow::sOOPPPluginFocusEvent =
|
||||
|
||||
MSG nsWindow::sRedirectedKeyDown;
|
||||
|
||||
PRBool nsWindow::sNeedsToInitMouseWheelSettings = PR_TRUE;
|
||||
ULONG nsWindow::sMouseWheelScrollLines = 0;
|
||||
ULONG nsWindow::sMouseWheelScrollChars = 0;
|
||||
|
||||
HWND nsWindow::sLastMouseWheelWnd = NULL;
|
||||
PRInt32 nsWindow::sRemainingDeltaForScroll = 0;
|
||||
PRInt32 nsWindow::sRemainingDeltaForPixel = 0;
|
||||
PRBool nsWindow::sLastMouseWheelDeltaIsPositive = PR_FALSE;
|
||||
PRBool nsWindow::sLastMouseWheelOrientationIsVertical = PR_FALSE;
|
||||
PRBool nsWindow::sLastMouseWheelUnitIsPage = PR_FALSE;
|
||||
PRUint32 nsWindow::sLastMouseWheelTime = 0;
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* SECTION: globals variables
|
||||
@ -4524,8 +4536,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
||||
PRBool result = PR_FALSE; // call the default nsWindow proc
|
||||
*aRetValue = 0;
|
||||
|
||||
static PRBool getWheelInfo = PR_TRUE;
|
||||
|
||||
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
||||
// Glass hit testing w/custom transparent margins
|
||||
LRESULT dwmHitResult;
|
||||
@ -5187,7 +5197,12 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
||||
break;
|
||||
|
||||
case WM_SETTINGCHANGE:
|
||||
getWheelInfo = PR_TRUE;
|
||||
switch (wParam) {
|
||||
case SPI_SETWHEELSCROLLLINES:
|
||||
case SPI_SETWHEELSCROLLCHARS:
|
||||
sNeedsToInitMouseWheelSettings = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_INPUTLANGCHANGEREQUEST:
|
||||
@ -5259,8 +5274,9 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
||||
// If OnMouseWheel returns false, OnMouseWheel processed the event internally.
|
||||
// 'result' and 'aRetValue' will be set based on what we did with the event, so
|
||||
// we should fall through.
|
||||
if (OnMouseWheel(msg, wParam, lParam, getWheelInfo, result, aRetValue))
|
||||
if (OnMouseWheel(msg, wParam, lParam, result, aRetValue)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -6281,118 +6297,152 @@ PRUint16 nsWindow::GetMouseInputSource()
|
||||
return inputSource;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsWindow::InitMouseWheelScrollData()
|
||||
{
|
||||
if (!sNeedsToInitMouseWheelSettings) {
|
||||
return;
|
||||
}
|
||||
sNeedsToInitMouseWheelSettings = PR_FALSE;
|
||||
ResetRemainingWheelDelta();
|
||||
|
||||
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
|
||||
&sMouseWheelScrollLines, 0)) {
|
||||
NS_WARNING("Failed to get SPI_GETWHEELSCROLLLINES");
|
||||
sMouseWheelScrollLines = 3;
|
||||
} else if (sMouseWheelScrollLines > WHEEL_DELTA) {
|
||||
// sMouseWheelScrollLines usually equals 3 or 0 (for no scrolling)
|
||||
// However, if sMouseWheelScrollLines > WHEEL_DELTA, we assume that
|
||||
// the mouse driver wants a page scroll. The docs state that
|
||||
// sMouseWheelScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
||||
// since some mouse drivers use an arbitrary large number instead,
|
||||
// we have to handle that as well.
|
||||
sMouseWheelScrollLines = WHEEL_PAGESCROLL;
|
||||
}
|
||||
|
||||
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
||||
&sMouseWheelScrollChars, 0)) {
|
||||
NS_ASSERTION(!nsUXThemeData::sIsVistaOrLater,
|
||||
"Failed to get SPI_GETWHEELSCROLLCHARS");
|
||||
sMouseWheelScrollChars = 1;
|
||||
} else if (sMouseWheelScrollChars > WHEEL_DELTA) {
|
||||
// See the comments for the case sMouseWheelScrollLines > WHEEL_DELTA.
|
||||
sMouseWheelScrollChars = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsWindow::ResetRemainingWheelDelta()
|
||||
{
|
||||
sRemainingDeltaForPixel = 0;
|
||||
sRemainingDeltaForScroll = 0;
|
||||
sLastMouseWheelWnd = NULL;
|
||||
}
|
||||
|
||||
static PRInt32 RoundDelta(double aDelta)
|
||||
{
|
||||
return aDelta >= 0 ? (PRInt32)NS_floor(aDelta) : (PRInt32)NS_ceil(aDelta);
|
||||
}
|
||||
|
||||
/*
|
||||
* OnMouseWheel - mouse wheel event processing. This was originally embedded
|
||||
* within the message case block. If returning true result should be returned
|
||||
* immediately (no more processing).
|
||||
*/
|
||||
PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& getWheelInfo, PRBool& result, LRESULT *aRetValue)
|
||||
PRBool
|
||||
nsWindow::OnMouseWheel(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
|
||||
PRBool& aHandled, LRESULT *aRetValue)
|
||||
{
|
||||
// Handle both flavors of mouse wheel events.
|
||||
static int iDeltaPerLine, iDeltaPerChar;
|
||||
static ULONG ulScrollLines, ulScrollChars = 1;
|
||||
static int currentVDelta, currentHDelta;
|
||||
static HWND currentWindow = 0;
|
||||
InitMouseWheelScrollData();
|
||||
|
||||
PRBool isVertical = msg == WM_MOUSEWHEEL;
|
||||
|
||||
// Get mouse wheel metrics (but only once).
|
||||
if (getWheelInfo) {
|
||||
getWheelInfo = PR_FALSE;
|
||||
|
||||
SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0);
|
||||
|
||||
// ulScrollLines usually equals 3 or 0 (for no scrolling)
|
||||
// WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
|
||||
|
||||
// However, if ulScrollLines > WHEEL_DELTA, we assume that
|
||||
// the mouse driver wants a page scroll. The docs state that
|
||||
// ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
||||
// since some mouse drivers use an arbitrary large number instead,
|
||||
// we have to handle that as well.
|
||||
|
||||
iDeltaPerLine = 0;
|
||||
if (ulScrollLines) {
|
||||
if (ulScrollLines <= WHEEL_DELTA) {
|
||||
iDeltaPerLine = WHEEL_DELTA / ulScrollLines;
|
||||
} else {
|
||||
ulScrollLines = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
||||
&ulScrollChars, 0)) {
|
||||
// Note that we may always fail to get the value before Win Vista.
|
||||
ulScrollChars = 1;
|
||||
}
|
||||
|
||||
iDeltaPerChar = 0;
|
||||
if (ulScrollChars) {
|
||||
if (ulScrollChars <= WHEEL_DELTA) {
|
||||
iDeltaPerChar = WHEEL_DELTA / ulScrollChars;
|
||||
} else {
|
||||
ulScrollChars = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
PRBool isVertical = (aMessage == WM_MOUSEWHEEL);
|
||||
if ((isVertical && sMouseWheelScrollLines == 0) ||
|
||||
(!isVertical && sMouseWheelScrollChars == 0)) {
|
||||
// XXX I think that we should dispatch mouse wheel events even if the
|
||||
// operation will not scroll because the wheel operation really happened
|
||||
// and web application may want to handle the event for non-scroll action.
|
||||
ResetRemainingWheelDelta();
|
||||
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
||||
aHandled = PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((isVertical && ulScrollLines != WHEEL_PAGESCROLL && !iDeltaPerLine) ||
|
||||
(!isVertical && ulScrollChars != WHEEL_PAGESCROLL && !iDeltaPerChar))
|
||||
return PR_FALSE; // break
|
||||
|
||||
// The mousewheel event will be dispatched to the toplevel
|
||||
// window. We need to give it to the child window.
|
||||
PRBool quit;
|
||||
if (!HandleScrollingPlugins(msg, wParam, lParam, result, aRetValue, quit))
|
||||
if (!HandleScrollingPlugins(aMessage, aWParam, aLParam,
|
||||
aHandled, aRetValue, quit)) {
|
||||
ResetRemainingWheelDelta();
|
||||
return quit; // return immediately if it's not our window
|
||||
}
|
||||
|
||||
// We should cancel the surplus delta if the current window is not
|
||||
// same as previous.
|
||||
if (currentWindow != mWnd) {
|
||||
currentVDelta = 0;
|
||||
currentHDelta = 0;
|
||||
currentWindow = mWnd;
|
||||
}
|
||||
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
scrollEvent.delta = 0;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
|
||||
if (ulScrollLines == WHEEL_PAGESCROLL) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? -1 : 1;
|
||||
} else {
|
||||
currentVDelta -= (short) HIWORD (wParam);
|
||||
if (PR_ABS(currentVDelta) >= iDeltaPerLine) {
|
||||
scrollEvent.delta = currentVDelta / iDeltaPerLine;
|
||||
currentVDelta %= iDeltaPerLine;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
|
||||
if (ulScrollChars == WHEEL_PAGESCROLL) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? 1 : -1;
|
||||
} else {
|
||||
currentHDelta += (short) HIWORD (wParam);
|
||||
if (PR_ABS(currentHDelta) >= iDeltaPerChar) {
|
||||
scrollEvent.delta = currentHDelta / iDeltaPerChar;
|
||||
currentHDelta %= iDeltaPerChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollEvent.delta) {
|
||||
// We store the wheel delta, and it will be used next wheel message, so,
|
||||
// we consume this message actually. We shouldn't call next wndproc.
|
||||
result = PR_TRUE;
|
||||
return PR_FALSE; // break
|
||||
PRInt32 nativeDelta = (short)HIWORD(aWParam);
|
||||
if (!nativeDelta) {
|
||||
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
||||
aHandled = PR_FALSE;
|
||||
ResetRemainingWheelDelta();
|
||||
return PR_FALSE; // We cannot process this message
|
||||
}
|
||||
|
||||
// The event may go to a plug-in which already dispatched this message.
|
||||
// Then, the event can cause deadlock. We should unlock the sender here.
|
||||
::ReplyMessage(isVertical ? 0 : TRUE);
|
||||
|
||||
PRBool isPageScroll =
|
||||
((isVertical && sMouseWheelScrollLines == WHEEL_PAGESCROLL) ||
|
||||
(!isVertical && sMouseWheelScrollChars == WHEEL_PAGESCROLL));
|
||||
|
||||
// Discard the remaining delta if current wheel message and last one are
|
||||
// received by different window or to scroll different direction or
|
||||
// different unit scroll. Furthermore, if the last event was too old.
|
||||
PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||
if (sLastMouseWheelWnd &&
|
||||
(sLastMouseWheelWnd != mWnd ||
|
||||
sLastMouseWheelDeltaIsPositive != (nativeDelta > 0) ||
|
||||
sLastMouseWheelOrientationIsVertical != isVertical ||
|
||||
sLastMouseWheelUnitIsPage != isPageScroll ||
|
||||
now - sLastMouseWheelTime > 1500)) {
|
||||
ResetRemainingWheelDelta();
|
||||
}
|
||||
sLastMouseWheelWnd = mWnd;
|
||||
sLastMouseWheelDeltaIsPositive = (nativeDelta > 0);
|
||||
sLastMouseWheelOrientationIsVertical = isVertical;
|
||||
sLastMouseWheelUnitIsPage = isPageScroll;
|
||||
sLastMouseWheelTime = now;
|
||||
|
||||
nsMouseScrollEvent testEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
InitEvent(testEvent);
|
||||
testEvent.scrollFlags = isPageScroll ? nsMouseScrollEvent::kIsFullPage : 0;
|
||||
testEvent.scrollFlags |= isVertical ? nsMouseScrollEvent::kIsVertical :
|
||||
nsMouseScrollEvent::kIsHorizontal;
|
||||
testEvent.delta = sLastMouseWheelDeltaIsPositive ? -1 : 1;
|
||||
nsQueryContentEvent queryEvent(PR_TRUE, NS_QUERY_SCROLL_TARGET_INFO, this);
|
||||
InitEvent(queryEvent);
|
||||
queryEvent.InitForQueryScrollTargetInfo(&testEvent);
|
||||
DispatchWindowEvent(&queryEvent);
|
||||
// If the necessary interger isn't larger than 0, we should assume that
|
||||
// the event failed for us.
|
||||
if (queryEvent.mSucceeded) {
|
||||
if (isPageScroll) {
|
||||
if (isVertical) {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mPageHeight > 0);
|
||||
} else {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mPageWidth > 0);
|
||||
}
|
||||
} else {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mLineHeight > 0);
|
||||
}
|
||||
}
|
||||
|
||||
*aRetValue = isVertical ? FALSE : TRUE; // means we process this message
|
||||
nsModifierKeyState modKeyState;
|
||||
|
||||
// Our positive delta value means to bottom or right.
|
||||
// But positive nativeDelta value means to top or right.
|
||||
// Use orienter for computing our delta value.
|
||||
PRInt32 orienter = isVertical ? -1 : 1;
|
||||
|
||||
// Assume the Control key is down if the Elantech touchpad has sent the
|
||||
// mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in
|
||||
// OnKeyUp.)
|
||||
@ -6401,25 +6451,97 @@ PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& ge
|
||||
static_cast<DWORD>(::GetMessageTime()) < mAssumeWheelIsZoomUntil) {
|
||||
isControl = PR_TRUE;
|
||||
} else {
|
||||
isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
||||
isControl = modKeyState.mIsControlDown;
|
||||
}
|
||||
|
||||
scrollEvent.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
||||
scrollEvent.isControl = isControl;
|
||||
scrollEvent.isMeta = PR_FALSE;
|
||||
scrollEvent.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
InitEvent(scrollEvent);
|
||||
if (nsnull != mEventCallback) {
|
||||
result = DispatchWindowEvent(&scrollEvent);
|
||||
}
|
||||
// Note that we should return zero if we process WM_MOUSEWHEEL.
|
||||
// But if we process WM_MOUSEHWHEEL, we should return non-zero.
|
||||
// If the query event failed, we cannot send pixel events.
|
||||
scrollEvent.scrollFlags =
|
||||
queryEvent.mSucceeded ? nsMouseScrollEvent::kHasPixels : 0;
|
||||
scrollEvent.isShift = modKeyState.mIsShiftDown;
|
||||
scrollEvent.isControl = isControl;
|
||||
scrollEvent.isMeta = PR_FALSE;
|
||||
scrollEvent.isAlt = modKeyState.mIsAltDown;
|
||||
|
||||
if (result)
|
||||
*aRetValue = isVertical ? 0 : TRUE;
|
||||
|
||||
return PR_FALSE; // break;
|
||||
}
|
||||
PRInt32 nativeDeltaForScroll = nativeDelta + sRemainingDeltaForScroll;
|
||||
|
||||
if (isPageScroll) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
||||
} else {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
||||
}
|
||||
scrollEvent.delta = nativeDeltaForScroll * orienter / WHEEL_DELTA;
|
||||
PRInt32 recomputedNativeDelta = scrollEvent.delta * orienter / WHEEL_DELTA;
|
||||
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
||||
} else {
|
||||
double deltaPerUnit;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
||||
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollLines;
|
||||
} else {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
||||
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollChars;
|
||||
}
|
||||
scrollEvent.delta =
|
||||
RoundDelta((double)nativeDeltaForScroll * orienter / deltaPerUnit);
|
||||
PRInt32 recomputedNativeDelta =
|
||||
(PRInt32)(scrollEvent.delta * orienter * deltaPerUnit);
|
||||
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
||||
}
|
||||
|
||||
if (scrollEvent.delta) {
|
||||
aHandled = DispatchWindowEvent(&scrollEvent);
|
||||
if (mOnDestroyCalled) {
|
||||
ResetRemainingWheelDelta();
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// If the query event failed, we cannot send pixel events.
|
||||
if (!queryEvent.mSucceeded) {
|
||||
sRemainingDeltaForPixel = 0;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsMouseScrollEvent pixelEvent(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, this);
|
||||
InitEvent(pixelEvent);
|
||||
pixelEvent.scrollFlags = nsMouseScrollEvent::kAllowSmoothScroll |
|
||||
(scrollEvent.scrollFlags & ~nsMouseScrollEvent::kHasPixels);
|
||||
pixelEvent.isShift = modKeyState.mIsShiftDown;
|
||||
pixelEvent.isControl = modKeyState.mIsControlDown;
|
||||
pixelEvent.isMeta = PR_FALSE;
|
||||
pixelEvent.isAlt = modKeyState.mIsAltDown;
|
||||
|
||||
PRInt32 nativeDeltaForPixel = nativeDelta + sRemainingDeltaForPixel;
|
||||
|
||||
double deltaPerPixel;
|
||||
if (isPageScroll) {
|
||||
if (isVertical) {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageHeight;
|
||||
} else {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageWidth;
|
||||
}
|
||||
} else {
|
||||
if (isVertical) {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollLines;
|
||||
} else {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollChars;
|
||||
}
|
||||
deltaPerPixel /= queryEvent.mReply.mLineHeight;
|
||||
}
|
||||
pixelEvent.delta =
|
||||
RoundDelta((double)nativeDeltaForPixel * orienter / deltaPerPixel);
|
||||
PRInt32 recomputedNativeDelta =
|
||||
(PRInt32)(pixelEvent.delta * orienter * deltaPerPixel);
|
||||
sRemainingDeltaForPixel = nativeDeltaForPixel - recomputedNativeDelta;
|
||||
if (pixelEvent.delta != 0) {
|
||||
aHandled = DispatchWindowEvent(&pixelEvent);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
|
||||
|
@ -411,8 +411,8 @@ protected:
|
||||
BOOL OnInputLangChange(HKL aHKL);
|
||||
PRBool OnPaint(HDC aDC, PRUint32 aNestingLevel);
|
||||
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
|
||||
PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
|
||||
PRBool& result, PRBool& getWheelInfo,
|
||||
PRBool OnMouseWheel(UINT aMessage, WPARAM aWParam,
|
||||
LPARAM aLParam, PRBool& aHandled,
|
||||
LRESULT *aRetValue);
|
||||
void OnWindowPosChanging(LPWINDOWPOS& info);
|
||||
|
||||
@ -616,6 +616,20 @@ protected:
|
||||
// was reirected to SendInput() API by OnKeyDown().
|
||||
static MSG sRedirectedKeyDown;
|
||||
|
||||
static PRBool sNeedsToInitMouseWheelSettings;
|
||||
static ULONG sMouseWheelScrollLines;
|
||||
static ULONG sMouseWheelScrollChars;
|
||||
static void InitMouseWheelScrollData();
|
||||
|
||||
static HWND sLastMouseWheelWnd;
|
||||
static PRInt32 sRemainingDeltaForScroll;
|
||||
static PRInt32 sRemainingDeltaForPixel;
|
||||
static PRBool sLastMouseWheelDeltaIsPositive;
|
||||
static PRBool sLastMouseWheelOrientationIsVertical;
|
||||
static PRBool sLastMouseWheelUnitIsPage;
|
||||
static PRUint32 sLastMouseWheelTime; // in milliseconds
|
||||
static void ResetRemainingWheelDelta();
|
||||
|
||||
// If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
|
||||
// redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event
|
||||
// because it has been dispatched before the message was redirected.
|
||||
@ -649,7 +663,6 @@ protected:
|
||||
nsRefPtr<nsWindow> mWindow;
|
||||
const MSG &mMsg;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -90,6 +90,10 @@
|
||||
#define SPI_GETWHEELSCROLLCHARS 0x006C
|
||||
#endif
|
||||
|
||||
#ifndef SPI_SETWHEELSCROLLCHARS
|
||||
#define SPI_SETWHEELSCROLLCHARS 0x006D
|
||||
#endif
|
||||
|
||||
#ifndef MAPVK_VSC_TO_VK
|
||||
#define MAPVK_VK_TO_VSC 0
|
||||
#define MAPVK_VSC_TO_VK 1
|
||||
|
Loading…
Reference in New Issue
Block a user