backing out Bug 343457 too see if it caused btek tp regression

This commit is contained in:
Olli.Pettay%helsinki.fi 2006-07-11 20:18:07 +00:00
parent 83c14b811f
commit ce0745a535
6 changed files with 54 additions and 187 deletions

View File

@ -94,14 +94,12 @@ class nsIStyleSheet;
class nsCSSFrameConstructor;
class nsISelection;
template<class E> class nsCOMArray;
class nsWeakFrame;
typedef short SelectionType;
#define NS_IPRESSHELL_IID \
{ 0x67880b18, 0xaf91, 0x431b, \
{ 0x89, 0x69, 0xfa, 0xd9, 0x2b, 0x3c, 0x33, 0x32 } }
{ 0xa736d2fd, 0x0191, 0x42ea, \
{ 0xb1, 0xb0, 0x80, 0x45, 0x1d, 0xfa, 0x03, 0x53 } }
// Constants uses for ScrollFrameIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -751,8 +749,6 @@ public:
nscolor aBackgroundColor,
nsIRenderingContext** aRenderedContext) = 0;
void AddWeakFrame(nsWeakFrame* aWeakFrame);
void RemoveWeakFrame(nsWeakFrame* aWeakFrame);
protected:
// IMPORTANT: The ownership implicit in the following member variables
// has been explicitly checked. If you add any members to this class,
@ -783,10 +779,7 @@ protected:
// Set to true when the accessibility service is being used to mirror
// the dom/layout trees
PRPackedBool mIsAccessibilityActive;
// A list of weak frames. This is a pointer to the last item in the list.
nsWeakFrame* mWeakFrames;
PRPackedBool mIsAccessibilityActive;
};
/**

View File

@ -1603,29 +1603,6 @@ nsIPresShell::GetVerifyReflowFlags()
#endif
}
void
nsIPresShell::AddWeakFrame(nsWeakFrame* aWeakFrame)
{
aWeakFrame->SetPreviousWeakFrame(mWeakFrames);
mWeakFrames = aWeakFrame;
}
void
nsIPresShell::RemoveWeakFrame(nsWeakFrame* aWeakFrame)
{
if (mWeakFrames == aWeakFrame) {
mWeakFrames = aWeakFrame->GetPreviousWeakFrame();
return;
}
nsWeakFrame* nextWeak = mWeakFrames;
while (nextWeak && nextWeak->GetPreviousWeakFrame() != aWeakFrame) {
nextWeak = nextWeak->GetPreviousWeakFrame();
}
if (nextWeak) {
nextWeak->SetPreviousWeakFrame(aWeakFrame->GetPreviousWeakFrame());
}
}
//----------------------------------------------------------------------
nsresult
@ -1954,11 +1931,6 @@ PresShell::Destroy()
mFrameConstructor->WillDestroyFrameTree();
FrameManager()->Destroy();
NS_WARN_IF_FALSE(!mWeakFrames, "Weak frames alive after destroying FrameManager");
while (mWeakFrames) {
mWeakFrames->Clear(this);
}
// Let the style set do its cleanup.
mStyleSet->Shutdown(mPresContext);
@ -3200,16 +3172,6 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
mPresContext->PropertyTable()->DeleteAllPropertiesFor(aFrame);
}
nsWeakFrame* weakFrame = mWeakFrames;
while (weakFrame) {
nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame();
if (weakFrame->GetFrame() == aFrame) {
// This removes weakFrame from mWeakFrames.
weakFrame->Clear(this);
}
weakFrame = prev;
}
return NS_OK;
}

View File

@ -1690,64 +1690,6 @@ private:
NS_IMETHOD_(nsrefcnt) Release(void) = 0;
};
//----------------------------------------------------------------------
/**
* nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
* Whenever an nsIFrame object is deleted, the nsWeakFrames pointing
* to it will be cleared.
*
* Create nsWeakFrame object when it is sure that nsIFrame object
* is alive and after some operations which may destroy the nsIFrame
* (for example any DOM modifications) use IsAlive() or GetFrame() methods to
* check whether it is safe to continue to use the nsIFrame object.
*
* @note The usage of this class should be kept to a minimum.
*/
class nsWeakFrame {
public:
nsWeakFrame(nsIFrame* aFrame)
{
mPrev = nsnull;
mFrame = aFrame;
if (mFrame) {
nsIPresShell* shell = mFrame->GetPresContext()->GetPresShell();
NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
if (shell) {
shell->AddWeakFrame(this);
} else {
mFrame = nsnull;
}
}
}
void Clear(nsIPresShell* aShell) {
if (aShell) {
aShell->RemoveWeakFrame(this);
}
mFrame = nsnull;
mPrev = nsnull;
}
PRBool IsAlive() { return !!mFrame; }
nsIFrame* GetFrame() { return mFrame; }
nsWeakFrame* GetPreviousWeakFrame() { return mPrev; }
void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
~nsWeakFrame()
{
Clear(mFrame ? mFrame->GetPresContext()->GetPresShell() : nsnull);
}
private:
nsWeakFrame* mPrev;
nsIFrame* mFrame;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrame, NS_IFRAME_IID)
#endif /* nsIFrame_h___ */

View File

@ -110,11 +110,8 @@ nsPopupBoxObject::HidePopup()
nsIPopupSetFrame *popupSet = GetPopupSetFrame();
nsIFrame *ourFrame = GetFrame(PR_FALSE);
if (ourFrame && popupSet) {
nsWeakFrame weakFrame(ourFrame);
popupSet->HidePopup(ourFrame);
if (weakFrame.IsAlive()) {
popupSet->DestroyPopup(ourFrame, PR_TRUE);
}
popupSet->DestroyPopup(ourFrame, PR_TRUE);
}
return NS_OK;

View File

@ -321,9 +321,8 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
const nsString& aPopupType, const nsString& anAnchorAlignment,
const nsString& aPopupAlignment)
{
nsWeakFrame weakFrame(this);
// First fire the popupshowing event.
if (!OnCreate(aXPos, aYPos, aPopupContent) || !weakFrame.IsAlive())
if (!OnCreate(aXPos, aYPos, aPopupContent))
return NS_OK;
// See if we already have an entry in our list. We must create a new one on a miss.
@ -349,7 +348,6 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
entry->mPopupFrame = GetPresContext()->PresShell()
->GetPrimaryFrameFor(aPopupContent);
nsWeakFrame weakPopupFrame(entry->mPopupFrame);
#ifdef DEBUG_PINK
printf("X Pos: %d\n", mXPos);
printf("Y Pos: %d\n", mYPos);
@ -358,26 +356,18 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
// Generate the popup.
entry->mCreateHandlerSucceeded = PR_TRUE;
entry->mIsOpen = PR_TRUE;
// This may destroy entry->mPopupFrame
MarkAsGenerated(aPopupContent);
// determine if this menu is a context menu and flag it
nsIFrame* activeChild = entry->mPopupFrame;
nsIMenuParent* childPopup = nsnull;
if (weakPopupFrame.IsAlive())
CallQueryInterface(weakPopupFrame.GetFrame(), &childPopup);
if (activeChild)
CallQueryInterface(activeChild, &childPopup);
if ( childPopup && aPopupType.EqualsLiteral("context") )
childPopup->SetIsContextMenu(PR_TRUE);
if (!weakFrame.IsAlive()) {
return NS_OK;
}
// Now open the popup.
OpenPopup(entry, PR_TRUE);
if (!weakFrame.IsAlive()) {
return NS_OK;
}
// Now fire the popupshown event.
OnCreated(aXPos, aYPos, aPopupContent);
@ -426,37 +416,34 @@ nsPopupSetFrame::DestroyPopup(nsIFrame* aPopup, PRBool aDestroyEntireChain)
nsPopupFrameList* entry = mPopupList->GetEntryByFrame(aPopup);
if (entry && entry->mCreateHandlerSucceeded) { // ensure the popup was created before we try to destroy it
nsWeakFrame weakFrame(this);
OpenPopup(entry, PR_FALSE);
nsCOMPtr<nsIContent> popupContent = entry->mPopupContent;
if (weakFrame.IsAlive()) {
entry->mPopupType.SetLength(0);
if (aDestroyEntireChain && entry->mElementContent && entry->mPopupType.EqualsLiteral("context")) {
// If we are a context menu, and if we are attached to a
// menupopup, then destroying us should also dismiss the parent
// menu popup.
if (entry->mElementContent->Tag() == nsXULAtoms::menupopup) {
nsIFrame* popupFrame = GetPresContext()->PresShell()
->GetPrimaryFrameFor(entry->mElementContent);
if (popupFrame) {
nsIMenuParent *menuParent;
if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) {
menuParent->DismissChain();
}
entry->mPopupType.SetLength(0);
if (aDestroyEntireChain && entry->mElementContent && entry->mPopupType.EqualsLiteral("context")) {
// If we are a context menu, and if we are attached to a
// menupopup, then destroying us should also dismiss the parent
// menu popup.
if (entry->mElementContent->Tag() == nsXULAtoms::menupopup) {
nsIFrame* popupFrame = GetPresContext()->PresShell()
->GetPrimaryFrameFor(entry->mElementContent);
if (popupFrame) {
nsIMenuParent *menuParent;
if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) {
menuParent->DismissChain();
}
}
}
// clear things out for next time
entry->mCreateHandlerSucceeded = PR_FALSE;
entry->mElementContent = nsnull;
entry->mXPos = entry->mYPos = 0;
entry->mLastPref.width = -1;
entry->mLastPref.height = -1;
}
// clear things out for next time
entry->mCreateHandlerSucceeded = PR_FALSE;
entry->mElementContent = nsnull;
entry->mXPos = entry->mYPos = 0;
entry->mLastPref.width = -1;
entry->mLastPref.height = -1;
// ungenerate the popup.
popupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, PR_TRUE);
entry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, PR_TRUE);
}
return NS_OK;
@ -478,26 +465,21 @@ nsPopupSetFrame::MarkAsGenerated(nsIContent* aPopupContent)
void
nsPopupSetFrame::OpenPopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
{
nsWeakFrame weakFrame(this);
nsIFrame* activeChild = aEntry->mPopupFrame;
nsWeakFrame weakPopupFrame(activeChild);
nsCOMPtr<nsIContent> popupContent = aEntry->mPopupContent;
PRBool createHandlerSucceeded = aEntry->mCreateHandlerSucceeded;
nsAutoString popupType = aEntry->mPopupType;
if (aActivateFlag) {
ActivatePopup(aEntry, PR_TRUE);
// register the rollup listeners, etc, but not if we're a tooltip
if (!popupType.EqualsLiteral("tooltip")) {
if (!aEntry->mPopupType.EqualsLiteral("tooltip")) {
nsIFrame* activeChild = aEntry->mPopupFrame;
nsIMenuParent* childPopup = nsnull;
if (weakPopupFrame.IsAlive())
if (activeChild)
CallQueryInterface(activeChild, &childPopup);
// Tooltips don't get keyboard navigation
if (childPopup && !nsMenuDismissalListener::sInstance) {
// First check and make sure this popup wants keyboard navigation
if (!popupContent->AttrValueIs(kNameSpaceID_None, nsXULAtoms::ignorekeys,
nsXULAtoms::_true, eCaseMatters))
if (!aEntry->mPopupContent->AttrValueIs(kNameSpaceID_None, nsXULAtoms::ignorekeys,
nsXULAtoms::_true, eCaseMatters))
childPopup->InstallKeyboardNavigator();
}
@ -507,32 +489,28 @@ nsPopupSetFrame::OpenPopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
}
}
else {
if (createHandlerSucceeded && !OnDestroy(aEntry->mPopupContent))
if (aEntry->mCreateHandlerSucceeded && !OnDestroy(aEntry->mPopupContent))
return;
// Unregister, but not if we're a tooltip
if (!popupType.EqualsLiteral("tooltip") ) {
if (!aEntry->mPopupType.EqualsLiteral("tooltip") ) {
nsMenuDismissalListener::Shutdown();
}
// Remove any keyboard navigators
nsIMenuParent* childPopup = nsnull;
if (weakPopupFrame.IsAlive())
CallQueryInterface(activeChild, &childPopup);
if (aEntry->mPopupFrame)
CallQueryInterface(aEntry->mPopupFrame, &childPopup);
if (childPopup)
childPopup->RemoveKeyboardNavigator();
nsRefPtr<nsPresContext> presContext = GetPresContext();
nsCOMPtr<nsIContent> content = aEntry->mPopupContent;
ActivatePopup(aEntry, PR_FALSE);
OnDestroyed(presContext, content);
OnDestroyed(aEntry->mPopupContent);
}
if (weakFrame.IsAlive()) {
nsBoxLayoutState state(GetPresContext());
MarkDirtyChildren(state); // Mark ourselves dirty.
}
nsBoxLayoutState state(GetPresContext());
MarkDirtyChildren(state); // Mark ourselves dirty.
}
void
@ -546,25 +524,23 @@ nsPopupSetFrame::ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
// XXXben hook in |width| and |height| usage here?
aEntry->mPopupContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, NS_LITERAL_STRING("true"), PR_TRUE);
else {
nsWeakFrame weakFrame(this);
nsWeakFrame weakActiveChild(aEntry->mPopupFrame);
nsCOMPtr<nsIContent> content = aEntry->mPopupContent;
content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE);
content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE);
aEntry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE);
aEntry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE);
// get rid of the reflows we just created. If we leave them hanging around, we
// can get into trouble if a dialog with a modal event loop comes along and
// processes the reflows before we get to call DestroyChain(). Processing the
// reflow will cause the popup to show itself again. (bug 71219)
nsIDocument* doc = content->GetDocument();
nsIDocument* doc = aEntry->mPopupContent->GetDocument();
if (doc)
doc->FlushPendingNotifications(Flush_OnlyReflow);
// make sure we hide the popup. We can't assume that we'll have a view
// since we could be cleaning up after someone that didn't correctly
// destroy the popup.
if (weakFrame.IsAlive() && weakActiveChild.IsAlive()) {
nsIView* view = weakActiveChild.GetFrame()->GetView();
nsIFrame* activeChild = aEntry->mPopupFrame;
if (activeChild) {
nsIView* view = activeChild->GetView();
NS_ASSERTION(view, "View is gone, looks like someone forgot to roll up the popup!");
if (view) {
nsIViewManager* viewManager = view->GetViewManager();
@ -573,7 +549,7 @@ nsPopupSetFrame::ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
viewManager->ResizeView(view, r);
if (aEntry->mIsOpen) {
aEntry->mIsOpen = PR_FALSE;
FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuInactive"), content);
FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuInactive"), aEntry->mPopupContent);
}
}
}
@ -594,7 +570,6 @@ nsPopupSetFrame::OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
event.refPoint.y = aY;
if (aPopupContent) {
nsCOMPtr<nsIContent> kungFuDeathGrip(aPopupContent);
nsIPresShell *shell = GetPresContext()->GetPresShell();
if (shell) {
nsresult rv = shell->HandleDOMEventWithTarget(aPopupContent, &event,
@ -697,15 +672,14 @@ nsPopupSetFrame::OnDestroy(nsIContent* aPopupContent)
}
PRBool
nsPopupSetFrame::OnDestroyed(nsPresContext* aPresContext,
nsIContent* aPopupContent)
nsPopupSetFrame::OnDestroyed(nsIContent* aPopupContent)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN, nsnull,
nsMouseEvent::eReal);
if (aPopupContent && aPresContext) {
nsIPresShell *shell = aPresContext->GetPresShell();
if (aPopupContent) {
nsIPresShell *shell = GetPresContext()->GetPresShell();
if (shell) {
nsresult rv = shell->HandleDOMEventWithTarget(aPopupContent, &event,
&status);

View File

@ -117,8 +117,7 @@ public:
PRBool OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent);
PRBool OnDestroy(nsIContent* aPopupContent);
PRBool OnCreated(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent);
static PRBool OnDestroyed(nsPresContext* aPresContext,
nsIContent* aPopupContent);
PRBool OnDestroyed(nsIContent* aPopupContent);
void ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag);
void OpenPopup(nsPopupFrameList* aEntry, PRBool aOpenFlag);