mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 00:50:40 +00:00
Bug 898871 - Add more nsWeakFrame checks around scroll operations. r=roc
This commit is contained in:
parent
b0c3d1c587
commit
a030bc32af
@ -643,7 +643,11 @@ nsListControlFrame::SingleSelection(int32_t aClickedIndex, bool aDoToggle)
|
||||
wasChanged = SetOptionsSelectedFromFrame(aClickedIndex, aClickedIndex,
|
||||
true, true);
|
||||
}
|
||||
nsWeakFrame weakFrame(this);
|
||||
ScrollToIndex(aClickedIndex);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return wasChanged;
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
bool isCurrentOptionChanged = mEndSelectionIndex != aClickedIndex;
|
||||
@ -775,7 +779,11 @@ nsListControlFrame::PerformSelection(int32_t aClickedIndex,
|
||||
|
||||
// Clear only if control was not pressed
|
||||
wasChanged = ExtendedSelection(startIndex, endIndex, !aIsControl);
|
||||
nsWeakFrame weakFrame(this);
|
||||
ScrollToIndex(aClickedIndex);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return wasChanged;
|
||||
}
|
||||
|
||||
if (mStartSelectionIndex == kNothingSelected) {
|
||||
mStartSelectionIndex = aClickedIndex;
|
||||
@ -792,12 +800,12 @@ nsListControlFrame::PerformSelection(int32_t aClickedIndex,
|
||||
}
|
||||
#endif
|
||||
} else if (aIsControl) {
|
||||
wasChanged = SingleSelection(aClickedIndex, true);
|
||||
wasChanged = SingleSelection(aClickedIndex, true); // might destroy us
|
||||
} else {
|
||||
wasChanged = SingleSelection(aClickedIndex, false);
|
||||
wasChanged = SingleSelection(aClickedIndex, false); // might destroy us
|
||||
}
|
||||
} else {
|
||||
wasChanged = SingleSelection(aClickedIndex, false);
|
||||
wasChanged = SingleSelection(aClickedIndex, false); // might destroy us
|
||||
}
|
||||
|
||||
return wasChanged;
|
||||
@ -817,7 +825,7 @@ nsListControlFrame::HandleListSelection(nsIDOMEvent* aEvent,
|
||||
mouseEvent->GetCtrlKey(&isControl);
|
||||
#endif
|
||||
mouseEvent->GetShiftKey(&isShift);
|
||||
return PerformSelection(aClickedIndex, isShift, isControl);
|
||||
return PerformSelection(aClickedIndex, isShift, isControl); // might destroy us
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
@ -1018,7 +1026,11 @@ nsListControlFrame::ResetList(bool aAllowScrolling)
|
||||
NS_ASSERTION(selectElement, "No select element!");
|
||||
if (selectElement) {
|
||||
selectElement->GetSelectedIndex(&indexToSelect);
|
||||
nsWeakFrame weakFrame(this);
|
||||
ScrollToIndex(indexToSelect);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1290,12 +1302,13 @@ nsListControlFrame::ComboboxFinish(int32_t aIndex)
|
||||
gLastKeyTime = 0;
|
||||
|
||||
if (mComboboxFrame) {
|
||||
PerformSelection(aIndex, false, false);
|
||||
nsWeakFrame weakFrame(this);
|
||||
PerformSelection(aIndex, false, false); // might destroy us
|
||||
if (!weakFrame.IsAlive() || !mComboboxFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t displayIndex = mComboboxFrame->GetIndexOfDisplayArea();
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
if (displayIndex != aIndex) {
|
||||
mComboboxFrame->RedisplaySelectedText(); // might destroy us
|
||||
}
|
||||
@ -1336,7 +1349,11 @@ nsListControlFrame::OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex)
|
||||
mComboboxFrame->UpdateRecentIndex(NS_SKIP_NOTIFY_INDEX);
|
||||
}
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
ScrollToIndex(aNewIndex);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
mStartSelectionIndex = aNewIndex;
|
||||
mEndSelectionIndex = aNewIndex;
|
||||
InvalidateFocus();
|
||||
@ -1398,7 +1415,11 @@ nsListControlFrame::AboutToDropDown()
|
||||
mLastDropdownBackstopColor);
|
||||
|
||||
if (mIsAllContentHere && mIsAllFramesHere && mHasBeenInitialized) {
|
||||
nsWeakFrame weakFrame(this);
|
||||
ScrollToIndex(GetSelectedIndex());
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
#ifdef ACCESSIBILITY
|
||||
FireMenuItemActiveEvent(); // Inform assistive tech what got focus
|
||||
#endif
|
||||
@ -1785,7 +1806,13 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
// Handle Like List
|
||||
mButtonDown = true;
|
||||
CaptureMouseEvents(true);
|
||||
mChangesSinceDragStart = HandleListSelection(aMouseEvent, selectedIndex);
|
||||
nsWeakFrame weakFrame(this);
|
||||
bool change =
|
||||
HandleListSelection(aMouseEvent, selectedIndex); // might destroy us
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
mChangesSinceDragStart = change;
|
||||
} else {
|
||||
// NOTE: the combo box is responsible for dropping it down
|
||||
if (mComboboxFrame) {
|
||||
@ -1827,12 +1854,12 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent)
|
||||
if (mComboboxFrame->IsDroppedDown()) {
|
||||
int32_t selectedIndex;
|
||||
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
|
||||
PerformSelection(selectedIndex, false, false);
|
||||
PerformSelection(selectedIndex, false, false); // might destroy us
|
||||
}
|
||||
}
|
||||
} else {// XXX - temporary until we get drag events
|
||||
if (mButtonDown) {
|
||||
return DragMove(aMouseEvent);
|
||||
return DragMove(aMouseEvent); // might destroy us
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
@ -1860,9 +1887,13 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent)
|
||||
#else
|
||||
mouseEvent->GetCtrlKey(&isControl);
|
||||
#endif
|
||||
nsWeakFrame weakFrame(this);
|
||||
// Turn SHIFT on when you are dragging, unless control is on.
|
||||
bool wasChanged = PerformSelection(selectedIndex,
|
||||
!isControl, isControl);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
mChangesSinceDragStart = mChangesSinceDragStart || wasChanged;
|
||||
}
|
||||
}
|
||||
@ -2283,6 +2314,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
|
||||
uint32_t numOptions = options->Length();
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
for (uint32_t i = 0; i < numOptions; ++i) {
|
||||
uint32_t index = (i + startIndex) % numOptions;
|
||||
nsRefPtr<dom::HTMLOptionElement> optionElement =
|
||||
@ -2300,7 +2332,11 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PerformSelection(index, keyEvent->IsShift(), isControlOrMeta)) {
|
||||
bool wasChanged = PerformSelection(index, keyEvent->IsShift(), isControlOrMeta);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!wasChanged) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2327,12 +2363,16 @@ nsListControlFrame::PostHandleKeyEvent(int32_t aNewIndex,
|
||||
|
||||
// If you hold control, but not shift, no key will actually do anything
|
||||
// except space.
|
||||
nsWeakFrame weakFrame(this);
|
||||
bool wasChanged = false;
|
||||
if (aIsControlOrMeta && !aIsShift && aCharCode != ' ') {
|
||||
mStartSelectionIndex = aNewIndex;
|
||||
mEndSelectionIndex = aNewIndex;
|
||||
InvalidateFocus();
|
||||
ScrollToIndex(aNewIndex);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
FireMenuItemActiveEvent();
|
||||
@ -2342,7 +2382,7 @@ nsListControlFrame::PostHandleKeyEvent(int32_t aNewIndex,
|
||||
} else {
|
||||
wasChanged = PerformSelection(aNewIndex, aIsShift, aIsControlOrMeta);
|
||||
}
|
||||
if (wasChanged) {
|
||||
if (wasChanged && weakFrame.IsAlive()) {
|
||||
// dispatch event, update combobox, etc.
|
||||
UpdateSelection();
|
||||
}
|
||||
|
@ -133,19 +133,19 @@ public:
|
||||
virtual void AboutToDropDown() MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* @note This method might destroy |this|.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void AboutToRollup() MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Dispatch a DOM onchange event synchroniously.
|
||||
* @note This method might destroy |this|.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void FireOnChange() MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Makes aIndex the selected option of a combobox list.
|
||||
* @note This method might destroy |this|.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ComboboxFinish(int32_t aIndex) MOZ_OVERRIDE;
|
||||
virtual void OnContentReset() MOZ_OVERRIDE;
|
||||
@ -162,13 +162,16 @@ public:
|
||||
NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) MOZ_OVERRIDE;
|
||||
NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
|
||||
|
||||
// mouse event listeners (both )
|
||||
nsresult MouseDown(nsIDOMEvent* aMouseEvent); // might destroy |this|
|
||||
nsresult MouseUp(nsIDOMEvent* aMouseEvent); // might destroy |this|
|
||||
/**
|
||||
* Mouse event listeners.
|
||||
* @note These methods might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
nsresult MouseDown(nsIDOMEvent* aMouseEvent);
|
||||
nsresult MouseUp(nsIDOMEvent* aMouseEvent);
|
||||
nsresult MouseMove(nsIDOMEvent* aMouseEvent);
|
||||
nsresult DragMove(nsIDOMEvent* aMouseEvent);
|
||||
nsresult KeyDown(nsIDOMEvent* aKeyEvent); // might destroy |this|
|
||||
nsresult KeyPress(nsIDOMEvent* aKeyEvent); // might destroy |this|
|
||||
nsresult KeyDown(nsIDOMEvent* aKeyEvent);
|
||||
nsresult KeyPress(nsIDOMEvent* aKeyEvent);
|
||||
|
||||
/**
|
||||
* Returns the options collection for mContent, if any.
|
||||
@ -254,6 +257,7 @@ public:
|
||||
protected:
|
||||
/**
|
||||
* Updates the selected text in a combobox and then calls FireOnChange().
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Returns false if calling it destroyed |this|.
|
||||
*/
|
||||
bool UpdateSelection();
|
||||
@ -268,12 +272,18 @@ protected:
|
||||
|
||||
/**
|
||||
* Toggles (show/hide) the combobox dropdown menu.
|
||||
* @note This method might destroy |this|.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void DropDownToggleKey(nsIDOMEvent* aKeyEvent);
|
||||
|
||||
nsresult IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToFrame(mozilla::dom::HTMLOptionElement& aOptElement);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToIndex(int32_t anIndex);
|
||||
|
||||
/**
|
||||
@ -342,11 +352,20 @@ protected:
|
||||
bool aValue,
|
||||
bool aClearAll);
|
||||
bool ToggleOptionSelectedFromFrame(int32_t aIndex);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
bool SingleSelection(int32_t aClickedIndex, bool aDoToggle);
|
||||
bool ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
|
||||
bool aClearAll);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
bool PerformSelection(int32_t aClickedIndex, bool aIsShift,
|
||||
bool aIsControl);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
bool HandleListSelection(nsIDOMEvent * aDOMEvent, int32_t selectedIndex);
|
||||
void InitSelectionRange(int32_t aClickedIndex);
|
||||
void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
|
||||
|
@ -1578,13 +1578,18 @@ nsGfxScrollFrameInner::AsyncScrollCallback(void* anInstance, mozilla::TimeStamp
|
||||
nsRect intermediateRange =
|
||||
nsRect(self->GetScrollPosition(), nsSize()).UnionEdges(range);
|
||||
self->ScrollToImpl(destination, intermediateRange);
|
||||
// 'self' might be destroyed here
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply desired destination range since this is the last step of scrolling.
|
||||
self->mAsyncScroll = nullptr;
|
||||
nsWeakFrame weakFrame(self->mOuter);
|
||||
self->ScrollToImpl(self->mDestination, range);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
// We are done scrolling, set our destination to wherever we actually ended
|
||||
// up scrolling to.
|
||||
self->mDestination = self->GetScrollPosition();
|
||||
@ -1612,6 +1617,7 @@ nsGfxScrollFrameInner::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition)
|
||||
range.height = 0;
|
||||
}
|
||||
ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
// 'this' might be destroyed here
|
||||
}
|
||||
|
||||
void
|
||||
@ -1621,6 +1627,7 @@ nsGfxScrollFrameInner::ScrollToCSSPixelsApproximate(const CSSPoint& aScrollPosit
|
||||
nscoord halfRange = nsPresContext::CSSPixelsToAppUnits(1000);
|
||||
nsRect range(pt.x - halfRange, pt.y - halfRange, 2*halfRange - 1, 2*halfRange - 1);
|
||||
ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
// 'this' might be destroyed here
|
||||
}
|
||||
|
||||
CSSIntPoint
|
||||
@ -1648,7 +1655,11 @@ nsGfxScrollFrameInner::ScrollToWithOrigin(nsPoint aScrollPosition,
|
||||
// Asynchronous scrolling is not allowed, so we'll kill any existing
|
||||
// async-scrolling process and do an instant scroll.
|
||||
mAsyncScroll = nullptr;
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollToImpl(mDestination, range);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
// We are done scrolling, set our destination to wherever we actually ended
|
||||
// up scrolling to.
|
||||
mDestination = GetScrollPosition();
|
||||
@ -1664,7 +1675,11 @@ nsGfxScrollFrameInner::ScrollToWithOrigin(nsPoint aScrollPosition,
|
||||
if (!mAsyncScroll->SetRefreshObserver(this)) {
|
||||
mAsyncScroll = nullptr;
|
||||
// Observer setup failed. Scroll the normal way.
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollToImpl(mDestination, range);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
// We are done scrolling, set our destination to wherever we actually
|
||||
// ended up scrolling to.
|
||||
mDestination = GetScrollPosition();
|
||||
@ -2009,7 +2024,11 @@ nsGfxScrollFrameInner::ScrollToImpl(nsPoint aPt, const nsRect& aRange)
|
||||
ScrollVisual(oldScrollFramePos);
|
||||
|
||||
ScheduleSyntheticMouseMove();
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
UpdateScrollbarPosition();
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
PostScrollEvent();
|
||||
|
||||
// notify the listeners.
|
||||
@ -2472,6 +2491,7 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoint aDelta,
|
||||
AdjustForWholeDelta(aDelta.x, &pos.x);
|
||||
AdjustForWholeDelta(aDelta.y, &pos.y);
|
||||
ScrollTo(pos, aMode);
|
||||
// 'this' might be destroyed here
|
||||
if (aOverflow) {
|
||||
*aOverflow = nsIntPoint(0, 0);
|
||||
}
|
||||
@ -2494,7 +2514,11 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoint aDelta,
|
||||
rangeLowerY,
|
||||
rangeUpperX - rangeLowerX,
|
||||
rangeUpperY - rangeLowerY);
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollToWithOrigin(newPos, aMode, aOrigin, &range);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOverflow) {
|
||||
nsPoint clampAmount = newPos - mDestination;
|
||||
@ -2655,7 +2679,11 @@ nsGfxScrollFrameInner::ScrollToRestoredPosition()
|
||||
// convert from logical to physical scroll position
|
||||
scrollToPos.x = mScrollPort.x -
|
||||
(mScrollPort.XMost() - scrollToPos.x - mScrolledFrame->GetRect().width);
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollTo(scrollToPos, nsIScrollableFrame::INSTANT);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
// Re-get the scroll position, it might not be exactly equal to
|
||||
// mRestorePos due to rounding and clamping.
|
||||
mLastPos = GetLogicalScrollPosition();
|
||||
@ -2959,16 +2987,23 @@ nsGfxScrollFrameInner::Destroy()
|
||||
void
|
||||
nsGfxScrollFrameInner::UpdateScrollbarPosition()
|
||||
{
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
mFrameIsUpdatingScrollbar = true;
|
||||
|
||||
nsPoint pt = GetScrollPosition();
|
||||
if (mVScrollbarBox) {
|
||||
SetCoordAttribute(mVScrollbarBox->GetContent(), nsGkAtoms::curpos,
|
||||
pt.y - GetScrolledRect().y);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mHScrollbarBox) {
|
||||
SetCoordAttribute(mHScrollbarBox->GetContent(), nsGkAtoms::curpos,
|
||||
pt.x - GetScrolledRect().x);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mFrameIsUpdatingScrollbar = false;
|
||||
@ -3024,11 +3059,16 @@ void nsGfxScrollFrameInner::CurPosAttributeChanged(nsIContent* aContent)
|
||||
// didn't actually move yet. We need to make sure other listeners
|
||||
// see that the scroll position is not (yet) what they thought it
|
||||
// was.
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
UpdateScrollbarPosition();
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ScrollToWithOrigin(dest,
|
||||
isSmooth ? nsIScrollableFrame::SMOOTH : nsIScrollableFrame::INSTANT,
|
||||
nsGkAtoms::scrollbars, &allowedRange);
|
||||
// 'this' might be destroyed here
|
||||
}
|
||||
|
||||
/* ============= Scroll events ========== */
|
||||
@ -3600,7 +3640,8 @@ nsGfxScrollFrameInner::ReflowFinished()
|
||||
mHScrollbarBox ? mHScrollbarBox->GetContent() : nullptr;
|
||||
|
||||
// Note, in some cases mOuter may get deleted while finishing reflow
|
||||
// for scrollbars.
|
||||
// for scrollbars. XXXmats is this still true now that we have a script
|
||||
// blocker in this scope? (if not, remove the weak frame checks below).
|
||||
if (vScroll || hScroll) {
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
nsPoint scrollPos = GetScrollPosition();
|
||||
@ -3900,8 +3941,13 @@ nsGfxScrollFrameInner::SetCoordAttribute(nsIContent* aContent, nsIAtom* aAtom,
|
||||
if (aContent->AttrValueIs(kNameSpaceID_None, aAtom, newValue, eCaseMatters))
|
||||
return;
|
||||
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
nsCOMPtr<nsIContent> kungFuDeathGrip = aContent;
|
||||
aContent->SetAttr(kNameSpaceID_None, aAtom, newValue, true);
|
||||
MOZ_ASSERT(ShellIsAlive(weakShell), "pres shell was destroyed by scrolling");
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mScrollbarActivity) {
|
||||
nsRefPtr<ScrollbarActivity> scrollbarActivity(mScrollbarActivity);
|
||||
|
@ -88,8 +88,12 @@ public:
|
||||
virtual bool ReflowFinished() MOZ_OVERRIDE;
|
||||
virtual void ReflowCallbackCanceled() MOZ_OVERRIDE;
|
||||
|
||||
// This gets called when the 'curpos' attribute on one of the scrollbars changes
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Called when the 'curpos' attribute on one of the scrollbars changes.
|
||||
*/
|
||||
void CurPosAttributeChanged(nsIContent* aChild);
|
||||
|
||||
void PostScrollEvent();
|
||||
void FireScrollEvent();
|
||||
void PostScrolledAreaEvent();
|
||||
@ -122,16 +126,29 @@ public:
|
||||
nsGfxScrollFrameInner *mInner;
|
||||
};
|
||||
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void FinishReflowForScrollbar(nsIContent* aContent, nscoord aMinXY,
|
||||
nscoord aMaxXY, nscoord aCurPosXY,
|
||||
nscoord aPageIncrement,
|
||||
nscoord aIncrement);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void SetScrollbarEnabled(nsIContent* aContent, nscoord aMaxPos);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void SetCoordAttribute(nsIContent* aContent, nsIAtom* aAtom, nscoord aSize);
|
||||
|
||||
nscoord GetCoordAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aDefaultValue,
|
||||
nscoord* aRangeStart, nscoord* aRangeLength);
|
||||
|
||||
// Update scrollbar curpos attributes to reflect current scroll position
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Update scrollbar curpos attributes to reflect current scroll position
|
||||
*/
|
||||
void UpdateScrollbarPosition();
|
||||
|
||||
nsRect GetScrollPortRect() const { return mScrollPort; }
|
||||
@ -163,6 +180,7 @@ protected:
|
||||
public:
|
||||
static void AsyncScrollCallback(void* anInstance, mozilla::TimeStamp aTime);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* aRange is the range of allowable scroll positions around the desired
|
||||
* aScrollPosition. Null means only aScrollPosition is allowed.
|
||||
* This is a closed-ended range --- aRange.XMost()/aRange.YMost() are allowed.
|
||||
@ -171,14 +189,31 @@ public:
|
||||
const nsRect* aRange = nullptr) {
|
||||
ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other, aRange);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition);
|
||||
|
||||
CSSIntPoint GetScrollPositionCSSPixels();
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange);
|
||||
void ScrollVisual(nsPoint aOldScrolledFramePosition);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit,
|
||||
nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToRestoredPosition();
|
||||
|
||||
nsSize GetLineScrollAmount() const;
|
||||
nsSize GetPageScrollAmount() const;
|
||||
|
||||
@ -360,6 +395,9 @@ public:
|
||||
bool mHasBeenScrolled:1;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToWithOrigin(nsPoint aScrollPosition,
|
||||
nsIScrollableFrame::ScrollMode aMode,
|
||||
nsIAtom *aOrigin, // nullptr indicates "other" origin
|
||||
@ -522,23 +560,38 @@ public:
|
||||
virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
|
||||
return mInner.GetPageScrollAmount();
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
|
||||
const nsRect* aRange = nullptr) MOZ_OVERRIDE {
|
||||
mInner.ScrollTo(aScrollPosition, aMode, aRange);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mInner.ScrollToCSSPixels(aScrollPosition);
|
||||
}
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mInner.ScrollToCSSPixelsApproximate(aScrollPosition);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual CSSIntPoint GetScrollPositionCSSPixels() MOZ_OVERRIDE {
|
||||
return mInner.GetScrollPositionCSSPixels();
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
|
||||
nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollToRestoredPosition() MOZ_OVERRIDE {
|
||||
mInner.ScrollToRestoredPosition();
|
||||
}
|
||||
@ -548,6 +601,9 @@ public:
|
||||
virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
|
||||
mInner.RemoveScrollPositionListener(aListener);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
|
||||
mInner.CurPosAttributeChanged(aChild);
|
||||
}
|
||||
@ -791,10 +847,16 @@ public:
|
||||
virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
|
||||
return mInner.GetPageScrollAmount();
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
|
||||
const nsRect* aRange = nullptr) MOZ_OVERRIDE {
|
||||
mInner.ScrollTo(aScrollPosition, aMode, aRange);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mInner.ScrollToCSSPixels(aScrollPosition);
|
||||
}
|
||||
@ -804,10 +866,16 @@ public:
|
||||
virtual CSSIntPoint GetScrollPositionCSSPixels() MOZ_OVERRIDE {
|
||||
return mInner.GetScrollPositionCSSPixels();
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
|
||||
nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollToRestoredPosition() MOZ_OVERRIDE {
|
||||
mInner.ScrollToRestoredPosition();
|
||||
}
|
||||
@ -817,6 +885,9 @@ public:
|
||||
virtual void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) MOZ_OVERRIDE {
|
||||
mInner.RemoveScrollPositionListener(aListener);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void CurPosAttributeChanged(nsIContent* aChild) MOZ_OVERRIDE {
|
||||
mInner.CurPosAttributeChanged(aChild);
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ public:
|
||||
*/
|
||||
enum ScrollMode { INSTANT, SMOOTH, NORMAL };
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Clamps aScrollPosition to GetScrollRange and sets the scroll position
|
||||
* to that value.
|
||||
* @param aRange If non-null, specifies area which contains aScrollPosition
|
||||
@ -164,6 +165,7 @@ public:
|
||||
virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
|
||||
const nsRect* aRange = nullptr) = 0;
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Scrolls to a particular position in integer CSS pixels.
|
||||
* Keeps the exact current horizontal or vertical position if the current
|
||||
* position, rounded to CSS pixels, matches aScrollPosition. If
|
||||
@ -175,6 +177,7 @@ public:
|
||||
*/
|
||||
virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) = 0;
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Scrolls to a particular position in float CSS pixels.
|
||||
* This does not guarantee that GetScrollPositionCSSPixels equals
|
||||
* aScrollPosition afterward. It tries to scroll as close to
|
||||
@ -194,6 +197,7 @@ public:
|
||||
*/
|
||||
enum ScrollUnit { DEVICE_PIXELS, LINES, PAGES, WHOLE };
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Modifies the current scroll position by aDelta units given by aUnit,
|
||||
* clamping it to GetScrollRange. If WHOLE is specified as the unit,
|
||||
* content is scrolled all the way in the direction(s) given by aDelta.
|
||||
@ -205,6 +209,7 @@ public:
|
||||
virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
|
||||
nsIntPoint* aOverflow = nullptr, nsIAtom *aOrigin = nullptr) = 0;
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* This tells the scroll frame to try scrolling to the scroll
|
||||
* position that was restored from the history. This must be called
|
||||
* at least once after state has been restored. It is called by the
|
||||
|
@ -924,8 +924,12 @@ nsListBoxBodyFrame::VerticalScroll(int32_t aPosition)
|
||||
|
||||
nsPoint scrollPosition = scrollFrame->GetScrollPosition();
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
scrollFrame->ScrollTo(nsPoint(scrollPosition.x, aPosition),
|
||||
nsIScrollableFrame::INSTANT);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mYPosition = aPosition;
|
||||
}
|
||||
@ -1358,7 +1362,11 @@ nsListBoxBodyFrame::OnContentRemoved(nsPresContext* aPresContext,
|
||||
NS_PRECONDITION(mCurrentIndex > 0, "mCurrentIndex > 0");
|
||||
--mCurrentIndex;
|
||||
mYPosition = mCurrentIndex*mRowHeight;
|
||||
nsWeakFrame weakChildFrame(aChildFrame);
|
||||
VerticalScroll(mYPosition);
|
||||
if (!weakChildFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (mCurrentIndex > 0) {
|
||||
// At this point, we know we have a scrollbar, and we need to know
|
||||
@ -1382,7 +1390,11 @@ nsListBoxBodyFrame::OnContentRemoved(nsPresContext* aPresContext,
|
||||
mRowsToPrepend = 1;
|
||||
--mCurrentIndex;
|
||||
mYPosition = mCurrentIndex*mRowHeight;
|
||||
nsWeakFrame weakChildFrame(aChildFrame);
|
||||
VerticalScroll(mYPosition);
|
||||
if (!weakChildFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +400,11 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu, b
|
||||
if (mIsOpenChanged) {
|
||||
nsIScrollableFrame *scrollframe = do_QueryFrame(GetChildBox());
|
||||
if (scrollframe) {
|
||||
nsWeakFrame weakFrame(this);
|
||||
scrollframe->ScrollTo(nsPoint(0,0), nsIScrollableFrame::INSTANT);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
if (!scrollable)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> kungFuDeathGrip(mContent);
|
||||
scrollable->CurPosAttributeChanged(mContent);
|
||||
return rv;
|
||||
}
|
||||
|
@ -376,6 +376,7 @@ nsTreeBodyFrame::EnsureView()
|
||||
// Scroll to the given row.
|
||||
// XXX is this optimal if we haven't laid out yet?
|
||||
ScrollToRow(rowIndex);
|
||||
ENSURE_TRUE(weakFrame.IsAlive());
|
||||
|
||||
// Clear out the property info for the top row, but we always keep the
|
||||
// view current.
|
||||
@ -4134,9 +4135,12 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, int32_t aPosition
|
||||
Invalidate();
|
||||
|
||||
// Update the column scroll view
|
||||
nsWeakFrame weakFrame(this);
|
||||
aParts.mColumnsScrollFrame->ScrollTo(nsPoint(mHorzPosition, 0),
|
||||
nsIScrollableFrame::INSTANT);
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// And fire off an event about it all
|
||||
PostScrollEvent();
|
||||
return NS_OK;
|
||||
@ -4153,7 +4157,8 @@ nsTreeBodyFrame::ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aO
|
||||
else if (aNewIndex < aOldIndex)
|
||||
ScrollToRowInternal(parts, mTopRowIndex-1);
|
||||
} else {
|
||||
ScrollHorzInternal(parts, aNewIndex);
|
||||
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
UpdateScrollbars(parts);
|
||||
@ -4177,7 +4182,8 @@ nsTreeBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex
|
||||
ScrollInternal(parts, newrow);
|
||||
// Horizontal Scrollbar
|
||||
} else if (parts.mHScrollbar == aScrollbar) {
|
||||
ScrollHorzInternal(parts, aNewIndex);
|
||||
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
UpdateScrollbars(parts);
|
||||
|
Loading…
Reference in New Issue
Block a user