зеркало из https://github.com/mozilla/pjs.git
Don't crash if views were destroyed while flushing notifications. b=421839 r+sr=roc
This commit is contained in:
Родитель
3337889961
Коммит
d9338f796c
|
@ -297,6 +297,7 @@ public:
|
||||||
* @param aPoint is relative to the view.
|
* @param aPoint is relative to the view.
|
||||||
* @param aDelay is the timer's interval.
|
* @param aDelay is the timer's interval.
|
||||||
*/
|
*/
|
||||||
|
/*unsafe*/
|
||||||
nsresult StartAutoScrollTimer(nsIView *aView,
|
nsresult StartAutoScrollTimer(nsIView *aView,
|
||||||
nsPoint aPoint,
|
nsPoint aPoint,
|
||||||
PRUint32 aDelay);
|
PRUint32 aDelay);
|
||||||
|
@ -352,6 +353,7 @@ public:
|
||||||
* @param aIsSynchronous when PR_TRUE, scrolls the selection into view
|
* @param aIsSynchronous when PR_TRUE, scrolls the selection into view
|
||||||
* at some point after the method returns.request which is processed
|
* at some point after the method returns.request which is processed
|
||||||
*/
|
*/
|
||||||
|
/*unsafe*/
|
||||||
nsresult ScrollSelectionIntoView(SelectionType aType,
|
nsresult ScrollSelectionIntoView(SelectionType aType,
|
||||||
SelectionRegion aRegion,
|
SelectionRegion aRegion,
|
||||||
PRBool aIsSynchronous) const;
|
PRBool aIsSynchronous) const;
|
||||||
|
@ -558,7 +560,7 @@ public:
|
||||||
|
|
||||||
nsIPresShell *GetShell()const { return mShell; }
|
nsIPresShell *GetShell()const { return mShell; }
|
||||||
|
|
||||||
void DisconnectFromPresShell() { mShell = nsnull; }
|
void DisconnectFromPresShell() { StopAutoScrollTimer(); mShell = nsnull; }
|
||||||
private:
|
private:
|
||||||
nsresult TakeFocus(nsIContent *aNewFocus,
|
nsresult TakeFocus(nsIContent *aNewFocus,
|
||||||
PRUint32 aContentOffset,
|
PRUint32 aContentOffset,
|
||||||
|
|
|
@ -246,6 +246,7 @@ public:
|
||||||
SelectionDetails **aReturnDetails, SelectionType aType, PRBool aSlowCheck);
|
SelectionDetails **aReturnDetails, SelectionType aType, PRBool aSlowCheck);
|
||||||
NS_IMETHOD Repaint(nsPresContext* aPresContext);
|
NS_IMETHOD Repaint(nsPresContext* aPresContext);
|
||||||
|
|
||||||
|
// Note: StartAutoScrollTimer might destroy arbitrary frames, views etc.
|
||||||
nsresult StartAutoScrollTimer(nsPresContext *aPresContext,
|
nsresult StartAutoScrollTimer(nsPresContext *aPresContext,
|
||||||
nsIView *aView,
|
nsIView *aView,
|
||||||
nsPoint& aPoint,
|
nsPoint& aPoint,
|
||||||
|
@ -257,12 +258,15 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class nsAutoScrollTimer;
|
friend class nsAutoScrollTimer;
|
||||||
|
|
||||||
|
// Note: DoAutoScrollView might destroy arbitrary frames, views etc.
|
||||||
nsresult DoAutoScrollView(nsPresContext *aPresContext,
|
nsresult DoAutoScrollView(nsPresContext *aPresContext,
|
||||||
nsIView *aView,
|
nsIView *aView,
|
||||||
nsPoint& aPoint,
|
nsPoint& aPoint,
|
||||||
PRBool aScrollParentViews);
|
PRBool aScrollParentViews);
|
||||||
|
|
||||||
|
// Note: ScrollPointIntoClipView might destroy arbitrary frames, views etc.
|
||||||
nsresult ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll);
|
nsresult ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool *aDidScroll);
|
||||||
|
// Note: ScrollPointIntoView might destroy arbitrary frames, views etc.
|
||||||
nsresult ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool aScrollParentViews, PRBool *aDidScroll);
|
nsresult ScrollPointIntoView(nsPresContext *aPresContext, nsIView *aView, nsPoint& aPoint, PRBool aScrollParentViews, PRBool *aDidScroll);
|
||||||
nsresult GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, nscoord *aXOffset, nscoord *aYOffset);
|
nsresult GetViewAncestorOffset(nsIView *aView, nsIView *aAncestorView, nscoord *aXOffset, nscoord *aYOffset);
|
||||||
|
|
||||||
|
@ -5084,10 +5088,25 @@ nsTypedSelection::ScrollPointIntoClipView(nsPresContext *aPresContext, nsIView *
|
||||||
|
|
||||||
if (dx != 0 || dy != 0)
|
if (dx != 0 || dy != 0)
|
||||||
{
|
{
|
||||||
// Make sure latest bits are available before we scroll them.
|
nsCOMPtr<nsIPresShell> presShell;
|
||||||
aPresContext->GetViewManager()->Composite();
|
GetPresShell(getter_AddRefs(presShell));
|
||||||
|
NS_ASSERTION(presShell, "no pres shell");
|
||||||
|
|
||||||
// Now scroll the view!
|
nsWeakView weakView = scrollableView->View();
|
||||||
|
|
||||||
|
// Make sure latest bits are available before we scroll them. This flushes
|
||||||
|
// pending notifications and thus might destroy stuff (bug 421839).
|
||||||
|
// We need to hold a strong ref on the view manager to keep it alive.
|
||||||
|
nsCOMPtr<nsIViewManager> viewManager = aPresContext->GetViewManager();
|
||||||
|
viewManager->Composite();
|
||||||
|
|
||||||
|
if (!weakView.IsAlive()) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presShell->IsDestroying()) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
result = scrollableView->ScrollTo(bounds.x + dx, bounds.y + dy, 0);
|
result = scrollableView->ScrollTo(bounds.x + dx, bounds.y + dy, 0);
|
||||||
|
|
||||||
|
|
|
@ -1764,14 +1764,26 @@ void nsViewManager::UpdateWidgetsForView(nsView* aView)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aView, "Must have view!");
|
NS_PRECONDITION(aView, "Must have view!");
|
||||||
|
|
||||||
|
nsWeakView parentWeakView = aView;
|
||||||
if (aView->HasWidget()) {
|
if (aView->HasWidget()) {
|
||||||
aView->GetWidget()->Update();
|
aView->GetWidget()->Update(); // Flushes Layout!
|
||||||
|
if (!parentWeakView.IsAlive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nsView* childView = aView->GetFirstChild();
|
nsView* childView = aView->GetFirstChild();
|
||||||
childView;
|
while (childView) {
|
||||||
childView = childView->GetNextSibling()) {
|
nsWeakView childWeakView = childView;
|
||||||
UpdateWidgetsForView(childView);
|
UpdateWidgetsForView(childView);
|
||||||
|
if (NS_LIKELY(childWeakView.IsAlive())) {
|
||||||
|
childView = childView->GetNextSibling();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The current view was destroyed - restart at the first child if the
|
||||||
|
// parent is still alive.
|
||||||
|
childView = parentWeakView.IsAlive() ? aView->GetFirstChild() : nsnull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче