Merging cedar with mozilla-central.

This commit is contained in:
Mounir Lamouri 2011-05-17 15:32:32 +02:00
commit 0782c0f9f3
60 changed files with 1782 additions and 338 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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 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>

View 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>

View File

@ -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.

View 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>

View 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>

View 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>

View 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>

View File

@ -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,

View File

@ -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,

View File

@ -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[];

View File

@ -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),

View File

@ -346,6 +346,7 @@ private:
nsIDOMCSSValue* DoGetPageBreakBefore();
nsIDOMCSSValue* DoGetMozTransform();
nsIDOMCSSValue* DoGetMozTransformOrigin();
nsIDOMCSSValue* DoGetOrient();
/* User interface properties */
nsIDOMCSSValue* DoGetCursor();

View File

@ -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)
}

View File

@ -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));

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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>

View File

@ -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();

View File

@ -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":

View File

@ -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()
},

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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 = {

View File

@ -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) {
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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>

View File

@ -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;

View File

@ -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);
};

View File

@ -48,6 +48,9 @@ EXPORTS =
LIBRARY_NAME = jprof
EXPORT_LIBRARY = 1
# override optimization
MOZ_OPTIMIZE_FLAGS = -fno-omit-frame-pointer
CPPSRCS = \
libmalloc.cpp \
$(NULL)

View File

@ -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;

View File

@ -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];
};

View File

@ -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))
/*

View File

@ -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);
}
};

View File

@ -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:

View File

@ -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;

View File

@ -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. */

View File

@ -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!");
}

View File

@ -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,

View File

@ -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;
};
};
/**

View File

@ -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