Bug 348304, @nsMenuFrame::HandleEvent, r=enndeakin, sr=dbaron

This commit is contained in:
Olli.Pettay%helsinki.fi 2006-09-03 20:25:58 +00:00
Родитель 895d3338c5
Коммит 4364552a81
12 изменённых файлов: 351 добавлений и 108 удалений

Просмотреть файл

@ -360,11 +360,21 @@ nsMenuBarFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFl
nsIMenuFrame* result = FindMenuWithShortcut(aKeyEvent);
if (result) {
// We got one!
nsWeakFrame weakFrame(this);
nsIFrame* frame = nsnull;
CallQueryInterface(result, &frame);
nsWeakFrame weakResult(frame);
aHandledFlag = PR_TRUE;
SetActive(PR_TRUE);
SetCurrentMenuItem(result);
result->OpenMenu(PR_TRUE);
result->SelectFirstItem();
if (weakFrame.IsAlive()) {
SetCurrentMenuItem(result);
}
if (weakResult.IsAlive()) {
result->OpenMenu(PR_TRUE);
if (weakResult.IsAlive()) {
result->SelectFirstItem();
}
}
}
return NS_OK;
@ -377,7 +387,8 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
NS_DIRECTION_FROM_KEY_CODE(theDirection, aKeyCode);
if (!mCurrentMenu)
return NS_OK;
nsWeakFrame weakFrame(this);
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsContainer(isContainer);
@ -399,8 +410,13 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
GetNextMenuItem(mCurrentMenu) :
GetPreviousMenuItem(mCurrentMenu);
SetCurrentMenuItem(nextItem);
nsIFrame* nextFrame = nsnull;
if (nextItem) {
CallQueryInterface(nextItem, &nextFrame);
}
nsWeakFrame weakNext(nextFrame);
SetCurrentMenuItem(nextItem);
if (weakNext.IsAlive()) {
PRBool nextIsOpen;
nextItem->MenuIsOpen(nextIsOpen);
if (nextIsOpen) {
@ -410,9 +426,16 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
}
}
else if NS_DIRECTION_IS_BLOCK(theDirection) {
// Open the menu and select its first item.
mCurrentMenu->OpenMenu(PR_TRUE);
mCurrentMenu->SelectFirstItem();
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
nsIFrame* frame = nsnull;
CallQueryInterface(mCurrentMenu, &frame);
nsWeakFrame weakCurrentMenu(frame);
nsIMenuFrame* currentMenu = mCurrentMenu;
// Open the menu and select its first item.
currentMenu->OpenMenu(PR_TRUE);
if (weakCurrentMenu.IsAlive()) {
currentMenu->SelectFirstItem();
}
}
return NS_OK;
@ -537,18 +560,33 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
if (nsMenuFrame::GetContextMenu())
return NS_OK;
nsWeakFrame weakFrame(this);
// Unset the current child.
if (mCurrentMenu) {
mCurrentMenu->MenuIsOpen(wasOpen);
mCurrentMenu->SelectMenu(PR_FALSE);
if (wasOpen)
mCurrentMenu->OpenMenu(PR_FALSE);
nsIFrame* frame = nsnull;
CallQueryInterface(mCurrentMenu, &frame);
nsWeakFrame weakCurrentMenu(frame);
nsIMenuFrame* currentMenu = mCurrentMenu;
currentMenu->MenuIsOpen(wasOpen);
currentMenu->SelectMenu(PR_FALSE);
if (wasOpen && weakCurrentMenu.IsAlive()) {
currentMenu->OpenMenu(PR_FALSE);
}
}
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
// Set the new child.
if (aMenuItem) {
nsIFrame* newMenu = nsnull;
CallQueryInterface(aMenuItem, &newMenu);
nsWeakFrame weakNewMenu(newMenu);
aMenuItem->SelectMenu(PR_TRUE);
NS_ENSURE_TRUE(weakNewMenu.IsAlive(), NS_OK);
aMenuItem->MarkAsGenerated(); // Have the menu building. Get it ready to be shown.
NS_ENSURE_TRUE(weakNewMenu.IsAlive(), NS_OK);
PRBool isDisabled = PR_FALSE;
aMenuItem->MenuIsDisabled(isDisabled);
@ -557,6 +595,7 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
ClearRecentlyRolledUp();
}
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
mCurrentMenu = aMenuItem;
return NS_OK;
@ -569,6 +608,7 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
if (!mCurrentMenu)
return NS_OK;
nsWeakFrame weakFrame(this);
// See if our menu is open.
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
@ -576,10 +616,12 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
// Let the child menu handle this.
aHandledFlag = PR_FALSE;
mCurrentMenu->Escape(aHandledFlag);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (!aHandledFlag) {
// Close up this menu but keep our current menu item
// designation.
mCurrentMenu->OpenMenu(PR_FALSE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
nsMenuDismissalListener::Shutdown();
return NS_OK;
@ -587,6 +629,7 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
// Clear our current menu item if we've got one.
SetCurrentMenuItem(nsnull);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
SetActive(PR_FALSE);
@ -676,8 +719,11 @@ nsMenuBarFrame::DismissChain()
{
// Stop capturing rollups
nsMenuDismissalListener::Shutdown();
nsWeakFrame weakFrame(this);
SetCurrentMenuItem(nsnull);
SetActive(PR_FALSE);
if (weakFrame.IsAlive()) {
SetActive(PR_FALSE);
}
return NS_OK;
}

Просмотреть файл

@ -167,6 +167,40 @@ nsMenuFrame::SetParent(const nsIFrame* aParent)
return NS_OK;
}
class nsASyncMenuInitialization : public nsRunnable
{
public:
nsASyncMenuInitialization(nsIContent* aContent)
: mContent(aContent)
{
}
NS_IMETHOD Run() {
nsIDocument* doc = mContent ? mContent->GetCurrentDoc() : nsnull;
NS_ENSURE_TRUE(doc, NS_OK);
nsIPresShell* shell = doc->GetShellAt(0);
NS_ENSURE_TRUE(shell, NS_OK);
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
NS_ENSURE_TRUE(frame, NS_OK);
nsIMenuFrame* imenu = nsnull;
CallQueryInterface(frame, &imenu);
NS_ENSURE_TRUE(imenu, NS_OK);
nsMenuFrame* menu = NS_STATIC_CAST(nsMenuFrame*, imenu);
nsWeakFrame weakFrame(frame);
menu->UpdateMenuType(menu->GetPresContext());
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
menu->BuildAcceleratorText();
return NS_OK;
}
nsCOMPtr<nsIContent> mContent;
};
NS_IMETHODIMP
nsMenuFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
@ -187,9 +221,6 @@ nsMenuFrame::Init(nsIContent* aContent,
currFrame = currFrame->GetParent();
}
// Do the type="checkbox" magic
UpdateMenuType(GetPresContext());
//load the display strings for the keyboard accelerators, but only once
if (gRefCnt++ == 0) {
@ -223,9 +254,10 @@ nsMenuFrame::Init(nsIContent* aContent,
gControlText = new nsString(controlModifier);
gModifierSeparator = new nsString(modifierSeparator);
}
BuildAcceleratorText();
nsCOMPtr<nsIRunnable> ev =
new nsASyncMenuInitialization(GetContent());
NS_DispatchToCurrentThread(ev);
return rv;
}
@ -339,16 +371,19 @@ nsMenuFrame::Destroy()
// doesn't try to interact with a deallocated frame.
mTimerMediator->ClearFrame();
nsWeakFrame weakFrame(this);
// are we our menu parent's current menu item?
if (mMenuParent) {
nsIMenuFrame *curItem = mMenuParent->GetCurrentMenuItem();
if (curItem == this) {
// yes; tell it that we're going away
mMenuParent->SetCurrentMenuItem(nsnull);
ENSURE_TRUE(weakFrame.IsAlive());
}
}
UngenerateMenu();
ENSURE_TRUE(weakFrame.IsAlive());
DestroyPopupFrames(GetPresContext());
nsBoxFrame::Destroy();
}
@ -374,6 +409,7 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
nsWeakFrame weakFrame(this);
if (*aEventStatus == nsEventStatus_eIgnore)
*aEventStatus = nsEventStatus_eConsumeDoDefault;
@ -401,6 +437,7 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
// We have children.
if ( isMenuBar || !mMenuParent ) {
ToggleMenuState();
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (!IsOpen() && mMenuParent) {
// We closed up. The menu bar should always be
@ -488,6 +525,8 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
// Let the menu parent know we're the new item.
mMenuParent->SetCurrentMenuItem(this);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
NS_ENSURE_TRUE(mMenuParent, NS_OK);
// we need to check if we really became the current menu
// item or not
@ -519,9 +558,11 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
NS_IMETHODIMP
nsMenuFrame::ToggleMenuState()
{
{
nsWeakFrame weakFrame(this);
if (mMenuOpen) {
OpenMenu(PR_FALSE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
else {
PRBool justRolledUp = PR_FALSE;
@ -533,21 +574,28 @@ nsMenuFrame::ToggleMenuState()
// from the same click. Otherwise, the user can't click on
// a menubar item to toggle its submenu closed.
OpenMenu(PR_FALSE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
SelectMenu(PR_TRUE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
NS_ENSURE_TRUE(mMenuParent, NS_OK);
mMenuParent->SetActive(PR_FALSE);
}
else {
if (mMenuParent) {
mMenuParent->SetActive(PR_TRUE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
OpenMenu(PR_TRUE);
}
}
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (mMenuParent) {
// Make sure the current menu which is being toggled on
// the menubar is highlighted
mMenuParent->SetCurrentMenuItem(this);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
NS_ENSURE_TRUE(mMenuParent, NS_OK);
// We've successfully prevented the same click from both
// dismissing and reopening this menu.
// Clear the recent rollup state so we don't prevent
@ -567,6 +615,7 @@ nsMenuFrame::SelectMenu(PRBool aActivateFlag)
nsAutoString domEventToFire;
nsWeakFrame weakFrame(this);
if (aActivateFlag) {
if (mMenuParent) {
nsIMenuParent* ancestor = nsnull;
@ -587,7 +636,9 @@ nsMenuFrame::SelectMenu(PRBool aActivateFlag)
domEventToFire.AssignLiteral("DOMMenuItemInactive");
}
FireDOMEventSynch(domEventToFire);
if (weakFrame.IsAlive()) {
FireDOMEventSynch(domEventToFire);
}
return NS_OK;
}
@ -674,7 +725,10 @@ nsMenuFrame::ActivateMenu(PRBool aActivateFlag)
} else {
if (mMenuOpen) {
nsWeakFrame weakFrame(this);
nsWeakFrame weakPopup(menuPopup);
FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuInactive"), menuPopup->GetContent());
NS_ENSURE_TRUE(weakFrame.IsAlive() && weakPopup.IsAlive(), NS_OK);
}
nsIView* view = menuPopup->GetView();
NS_ASSERTION(view, "View is gone, looks like someone forgot to rollup the popup!");
@ -720,15 +774,22 @@ nsMenuFrame::OpenMenu(PRBool aActivateFlag)
if (!mContent)
return NS_OK;
nsWeakFrame weakFrame(this);
if (aActivateFlag) {
// Now that the menu is opened, we should have a menupopup child built.
// Mark it as generated, which ensures a frame gets built.
MarkAsGenerated();
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuItemActive"));
}
else mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::open, PR_TRUE);
else {
mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::open, PR_TRUE);
}
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
OpenMenuInternal(aActivateFlag);
return NS_OK;
@ -743,10 +804,11 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
return;
nsPresContext* presContext = GetPresContext();
nsWeakFrame weakFrame(this);
if (aActivateFlag) {
// Execute the oncreate handler
if (!OnCreate())
if (!OnCreate() || !weakFrame.IsAlive())
return;
mCreateHandlerSucceeded = PR_TRUE;
@ -757,6 +819,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// XXX Only have this here because of RDF-generated content.
MarkAsGenerated();
ENSURE_TRUE(weakFrame.IsAlive());
nsIFrame* frame = mPopupFrames.FirstChild();
nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame;
@ -765,11 +828,13 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
mMenuOpen = PR_TRUE;
if (menuPopup) {
nsWeakFrame weakMenuPopup(frame);
// inherit whether or not we're a context menu from the parent
if ( mMenuParent ) {
PRBool parentIsContextMenu = PR_FALSE;
mMenuParent->GetIsContextMenu(parentIsContextMenu);
menuPopup->SetIsContextMenu(parentIsContextMenu);
ENSURE_TRUE(weakFrame.IsAlive());
}
// Install a keyboard navigation listener if we're the root of the menu chain.
@ -779,12 +844,16 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
if (mMenuParent && onMenuBar)
mMenuParent->InstallKeyboardNavigator();
else if (!mMenuParent)
else if (!mMenuParent) {
ENSURE_TRUE(weakMenuPopup.IsAlive());
menuPopup->InstallKeyboardNavigator();
}
// Tell the menu bar we're active.
if (mMenuParent)
if (mMenuParent) {
mMenuParent->SetActive(PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
}
nsIContent* menuPopupContent = menuPopup->GetContent();
@ -841,6 +910,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
}
ActivateMenu(PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
nsIMenuParent *childPopup = nsnull;
CallQueryInterface(frame, &childPopup);
@ -850,6 +920,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
listener->SetCurrentMenuParent(childPopup);
OnCreated();
ENSURE_TRUE(weakFrame.IsAlive());
}
// Set the focus back to our view's widget.
@ -861,7 +932,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// Close the menu.
// Execute the ondestroy handler, but only if we're actually open
if ( !mCreateHandlerSucceeded || !OnDestroy() )
if ( !mCreateHandlerSucceeded || !OnDestroy() || !weakFrame.IsAlive())
return;
// Set the focus back to our view's widget.
@ -876,6 +947,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// Make sure we clear out our own items.
if (menuPopup) {
menuPopup->SetCurrentMenuItem(nsnull);
ENSURE_TRUE(weakFrame.IsAlive());
menuPopup->KillCloseTimer();
PRBool onMenuBar = PR_TRUE;
@ -901,6 +973,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
}
ActivateMenu(PR_FALSE);
ENSURE_TRUE(weakFrame.IsAlive());
// XXX hack: ensure that mMenuOpen is set to false, in case where
// there is actually no popup. because ActivateMenu() will return
// early without setting it. It could be that mMenuOpen is true
@ -911,6 +984,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
mMenuOpen = PR_FALSE;
OnDestroyed();
ENSURE_TRUE(weakFrame.IsAlive());
if (nsMenuDismissalListener::sInstance)
nsMenuDismissalListener::sInstance->EnableListener(PR_TRUE);
@ -1333,9 +1407,12 @@ nsMenuFrame::UpdateMenuType(nsPresContext* aPresContext)
break;
default:
if (mType != eMenuType_Normal)
if (mType != eMenuType_Normal) {
nsWeakFrame weakFrame(this);
mContent->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::checked,
PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
}
mType = eMenuType_Normal;
break;
}
@ -1440,7 +1517,9 @@ nsMenuFrame::BuildAcceleratorText()
AddStateBits(NS_STATE_ACCELTEXT_IS_DERIVED);
// If anything below fails, just leave the accelerator text blank.
nsWeakFrame weakFrame(this);
mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::acceltext, PR_FALSE);
ENSURE_TRUE(weakFrame.IsAlive());
// See if we have a key node and use that instead.
nsAutoString keyValue;
@ -1564,6 +1643,7 @@ nsMenuFrame::BuildAcceleratorText()
void
nsMenuFrame::Execute(nsGUIEvent *aEvent)
{
nsWeakFrame weakFrame(this);
// flip "checked" state if we're a checkbox menu, or an un-checked radio menu
if (mType == eMenuType_Checkbox || (mType == eMenuType_Radio && !mChecked)) {
if (!mContent->AttrValueIs(kNameSpaceID_None, nsHTMLAtoms::autocheck,
@ -1571,10 +1651,12 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
if (mChecked) {
mContent->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::checked,
PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
}
else {
mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::checked, NS_LITERAL_STRING("true"),
PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
}
/* the AttributeChanged code will update all the internal state */
}
@ -1592,6 +1674,7 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
// Deselect ourselves.
SelectMenu(PR_FALSE);
ENSURE_TRUE(weakFrame.IsAlive());
// Now hide all of the open menus.
if (mMenuParent) {
@ -1628,24 +1711,15 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
// See bug 54233.
nsPresContext* presContext = GetPresContext();
nsCOMPtr<nsIViewManager> kungFuDeathGrip = presContext->GetViewManager();
// keep a reference so we can safely use this after dispatching the DOM event
nsCOMPtr<nsIPresShell> shell = presContext->GetPresShell();
nsIFrame* me = this;
if (shell) {
shell->HandleDOMEventWithTarget(mContent, &event, &status);
// shell may no longer be alive, don't use it here unless you keep a ref
ENSURE_TRUE(weakFrame.IsAlive());
}
// XXX HACK. Just gracefully exit if the node has been removed, e.g., window.close()
// was executed.
nsIFrame* primary = nsnull;
if (shell) primary = shell->GetPrimaryFrameFor(content);
// Now properly close them all up.
if (content->GetDocument() && // <-- HACK IS HERE. ICK.
(primary == me) && mMenuParent)
if (mMenuParent) {
mMenuParent->DismissChain();
// END HACK
}
// Re-enable rollup events on this menu.
if ( nsMenuDismissalListener::sInstance ) {
@ -1688,7 +1762,7 @@ nsMenuFrame::OnCreate()
PRUint32 count = child->GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
nsIContent *grandChild = child->GetChildAt(i);
nsCOMPtr<nsIContent> grandChild = child->GetChildAt(i);
if (grandChild->Tag() == nsXULAtoms::menuitem) {
// See if we have a command attribute.
@ -1877,6 +1951,34 @@ nsMenuFrame::AppendFrames(nsIAtom* aListName,
return rv;
}
class nsASyncMenuGeneration : public nsRunnable
{
public:
nsASyncMenuGeneration(nsIContent* aContent)
: mContent(aContent)
{
}
NS_IMETHOD Run() {
nsIDocument* doc = mContent ? mContent->GetCurrentDoc() : nsnull;
NS_ENSURE_TRUE(doc, NS_OK);
nsIPresShell* shell = doc->GetShellAt(0);
NS_ENSURE_TRUE(shell, NS_OK);
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
NS_ENSURE_TRUE(frame, NS_OK);
nsIMenuFrame* imenu = nsnull;
CallQueryInterface(frame, &imenu);
NS_ENSURE_TRUE(imenu, NS_OK);
return imenu->MarkAsGenerated();
}
nsCOMPtr<nsIContent> mContent;
};
PRBool
nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
{
@ -1890,10 +1992,16 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
if (tmpSize.width == -1 && flex == 0) {
nsIFrame* frame = mPopupFrames.FirstChild();
if (!frame) {
MarkAsGenerated();
frame = mPopupFrames.FirstChild();
// No child - just return
if (!frame) return PR_FALSE;
nsCOMPtr<nsIContent> child;
GetMenuChildrenElement(getter_AddRefs(child));
if (child &&
!nsContentUtils::HasNonEmptyAttr(child, kNameSpaceID_None,
nsXULAtoms::menugenerated)) {
nsCOMPtr<nsIRunnable> ev =
new nsASyncMenuGeneration(GetContent());
NS_DispatchToCurrentThread(ev);
}
return PR_FALSE;
}
NS_ASSERTION(frame->IsBoxFrame(), "popupChild is not box!!");

Просмотреть файл

@ -92,6 +92,12 @@ private:
nsMenuFrame* mFrame;
};
/**
* @note *** Methods marked with '@see comment ***' may cause the frame to be
* deleted during the method call. Be careful whenever using those
* methods.
*/
class nsMenuFrame : public nsBoxFrame,
public nsIMenuFrame,
public nsIScrollableViewProvider
@ -123,7 +129,7 @@ public:
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
nsIFrame* aChildList);
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
virtual void Destroy();
virtual void Destroy(); // @see comment ***
// Overridden to prevent events from going to children of the menu.
NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
@ -132,7 +138,7 @@ public:
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
nsEventStatus* aEventStatus); // @see comment ***
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
@ -146,9 +152,9 @@ public:
// nsIMenuFrame Interface
NS_IMETHOD ActivateMenu(PRBool aActivateFlag);
NS_IMETHOD SelectMenu(PRBool aActivateFlag);
NS_IMETHOD OpenMenu(PRBool aActivateFlag);
NS_IMETHOD ActivateMenu(PRBool aActivateFlag); // @see comment ***
NS_IMETHOD SelectMenu(PRBool aActivateFlag); // @see comment ***
NS_IMETHOD OpenMenu(PRBool aActivateFlag); // @see comment ***
NS_IMETHOD MenuIsOpen(PRBool& aResult) { aResult = IsOpen(); return NS_OK; }
NS_IMETHOD MenuIsContainer(PRBool& aResult) { aResult = IsMenu(); return NS_OK; }
@ -156,16 +162,16 @@ public:
NS_IMETHOD MenuIsDisabled(PRBool& aResult) { aResult = IsDisabled(); return NS_OK; }
NS_IMETHOD GetActiveChild(nsIDOMElement** aResult);
NS_IMETHOD SetActiveChild(nsIDOMElement* aChild);
NS_IMETHOD SetActiveChild(nsIDOMElement* aChild); // @see comment ***
NS_IMETHOD UngenerateMenu();
NS_IMETHOD UngenerateMenu(); // @see comment ***
NS_IMETHOD SelectFirstItem();
NS_IMETHOD SelectFirstItem(); // @see comment ***
NS_IMETHOD Escape(PRBool& aHandledFlag);
NS_IMETHOD Enter();
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag);
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag);
NS_IMETHOD Escape(PRBool& aHandledFlag); // @see comment ***
NS_IMETHOD Enter(); // @see comment ***
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag); // @see comment ***
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag); // @see comment ***
NS_IMETHOD SetParent(const nsIFrame* aParent);
@ -188,7 +194,7 @@ public:
PRBool IsMenu();
PRBool IsDisabled();
PRBool IsGenerated();
NS_IMETHOD ToggleMenuState();
NS_IMETHOD ToggleMenuState(); // @see comment ***
void SetIsMenu(PRBool aIsMenu) { mIsMenu = aIsMenu; };
@ -211,33 +217,34 @@ protected:
void
ConvertPosition(nsIContent* aPopupElt, nsString& aAnchor, nsString& aAlign);
void UpdateMenuType(nsPresContext* aPresContext);
void UpdateMenuSpecialState(nsPresContext* aPresContext);
friend class nsASyncMenuInitialization;
void UpdateMenuType(nsPresContext* aPresContext); // @see comment ***
void UpdateMenuSpecialState(nsPresContext* aPresContext); // @see comment ***
void OpenMenuInternal(PRBool aActivateFlag);
void OpenMenuInternal(PRBool aActivateFlag); // @see comment ***
void GetMenuChildrenElement(nsIContent** aResult);
// Examines the key node and builds the accelerator.
void BuildAcceleratorText();
void BuildAcceleratorText(); // @see comment ***
// Called to execute our command handler.
void Execute(nsGUIEvent *aEvent);
void Execute(nsGUIEvent *aEvent); // @see comment ***
// Called as a hook just before the menu gets opened.
PRBool OnCreate();
PRBool OnCreate(); // @see comment ***
// Called as a hook just after the menu gets opened.
PRBool OnCreated();
PRBool OnCreated(); // @see comment ***
// Called as a hook just before the menu goes away.
PRBool OnDestroy();
PRBool OnDestroy(); // @see comment ***
// Called as a hook just after the menu goes away.
PRBool OnDestroyed();
PRBool OnDestroyed(); // @see comment ***
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
PRInt32 aModType); // @see comment ***
virtual ~nsMenuFrame();
PRBool SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize);

Просмотреть файл

@ -740,7 +740,28 @@ nsMenuPopupFrame::MovePopupToOtherSideOfParent ( PRBool inFlushAboveBelow, PRInt
} // MovePopupToOtherSideOfParent
class nsASyncMenuActivation : public nsRunnable
{
public:
nsASyncMenuActivation(nsIContent* aContent)
: mContent(aContent)
{
}
NS_IMETHOD Run() {
if (mContent &&
!mContent->AttrValueIs(kNameSpaceID_None, nsXULAtoms::menuactive,
nsXULAtoms::_true, eCaseMatters) &&
mContent->AttrValueIs(kNameSpaceID_None, nsXULAtoms::menutobedisplayed,
nsXULAtoms::_true, eCaseMatters)) {
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menuactive,
NS_LITERAL_STRING("true"), PR_TRUE);
}
return NS_OK;
}
nsCOMPtr<nsIContent> mContent;
};
nsresult
nsMenuPopupFrame::SyncViewWithFrame(nsPresContext* aPresContext,
@ -1123,7 +1144,9 @@ nsMenuPopupFrame::SyncViewWithFrame(nsPresContext* aPresContext,
nsXULAtoms::_true, eCaseMatters) &&
mContent->AttrValueIs(kNameSpaceID_None, nsXULAtoms::menutobedisplayed,
nsXULAtoms::_true, eCaseMatters)) {
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, NS_LITERAL_STRING("true"), PR_TRUE);
nsCOMPtr<nsIRunnable> ev =
new nsASyncMenuActivation(mContent);
NS_DispatchToCurrentThread(ev);
}
return NS_OK;
@ -1666,10 +1689,14 @@ nsMenuPopupFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandled
nsIMenuFrame* result = FindMenuWithShortcut(aKeyEvent, action);
if (result) {
// We got one!
nsIFrame* frame = nsnull;
CallQueryInterface(result, &frame);
nsWeakFrame weakResult(frame);
aHandledFlag = PR_TRUE;
SetCurrentMenuItem(result);
if (action)
if (action && weakResult.IsAlive()) {
result->Enter();
}
}
return NS_OK;
@ -1705,6 +1732,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
PRBool isDisabled = PR_FALSE;
nsWeakFrame weakFrame(this);
if (mCurrentMenu) {
mCurrentMenu->MenuIsContainer(isContainer);
mCurrentMenu->MenuIsOpen(isOpen);
@ -1713,13 +1741,19 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
if (isOpen) {
// Give our child a shot.
mCurrentMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
else if (theDirection == eNavigationDirection_End &&
isContainer && !isDisabled) {
// The menu is not yet open. Open it and select the first item.
aHandledFlag = PR_TRUE;
nsIFrame* frame = nsnull;
CallQueryInterface(mCurrentMenu, &frame);
nsWeakFrame weakCurrentFrame(frame);
mCurrentMenu->OpenMenu(PR_TRUE);
NS_ENSURE_TRUE(weakCurrentFrame.IsAlive(), NS_OK);
mCurrentMenu->SelectFirstItem();
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
}
@ -1750,6 +1784,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
if (theDirection == eNavigationDirection_Start) {
// Close it up.
mCurrentMenu->OpenMenu(PR_FALSE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
// SelectMenu() so DOMMenuItemActive is fired for accessibility
mCurrentMenu->SelectMenu(PR_TRUE);
aHandledFlag = PR_TRUE;
@ -1789,6 +1824,7 @@ nsMenuPopupFrame::HideChain()
nsIFrame* frame = GetParent();
if (frame) {
nsWeakFrame weakMenu(frame);
nsIMenuFrame* menuFrame;
if (NS_FAILED(CallQueryInterface(frame, &menuFrame))) {
nsIPopupSetFrame* popupSetFrame = GetPopupSetFrame(GetPresContext());
@ -1799,7 +1835,9 @@ nsMenuPopupFrame::HideChain()
}
menuFrame->ActivateMenu(PR_FALSE);
NS_ENSURE_TRUE(weakMenu.IsAlive(), NS_OK);
menuFrame->SelectMenu(PR_FALSE);
NS_ENSURE_TRUE(weakMenu.IsAlive(), NS_OK);
// Get the parent.
nsIMenuParent *menuParent = menuFrame->GetMenuParent();
@ -1965,8 +2003,9 @@ nsMenuPopupFrame::MoveToAttributePosition()
xPos = left.ToInteger(&err1);
yPos = top.ToInteger(&err2);
if (NS_SUCCEEDED(err1) && NS_SUCCEEDED(err2))
MoveTo(xPos, yPos);
if (NS_SUCCEEDED(err1) && NS_SUCCEEDED(err2)) {
MoveToInternal(xPos, yPos);
}
}
@ -2102,9 +2141,22 @@ nsMenuPopupFrame::MoveTo(PRInt32 aLeft, PRInt32 aTop)
left.AppendInt(aLeft);
top.AppendInt(aTop);
nsWeakFrame weakFrame(this);
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::left, left, PR_FALSE);
if (!weakFrame.IsAlive()) {
return;
}
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::top, top, PR_FALSE);
if (!weakFrame.IsAlive()) {
return;
}
MoveToInternal(aLeft, aTop);
}
void
nsMenuPopupFrame::MoveToInternal(PRInt32 aLeft, PRInt32 aTop)
{
nsIView* view = GetView();
NS_ASSERTION(view->GetParent(), "Must have parent!");

Просмотреть файл

@ -197,6 +197,8 @@ public:
void EnsureMenuItemIsVisible(nsIMenuFrame* aMenuFrame);
// This sets 'left' and 'top' attributes.
// May kill the frame.
void MoveTo(PRInt32 aLeft, PRInt32 aTop);
void GetAutoPosition(PRBool* aShouldAutoPosition);
@ -210,6 +212,9 @@ protected:
friend class nsMenuPopupTimerMediator;
NS_HIDDEN_(nsresult) Notify(nsITimer* aTimer);
// Move without updating attributes.
void MoveToInternal(PRInt32 aLeft, PRInt32 aTop);
// redefine to tell the box system not to move the
// views.
virtual void GetLayoutFlags(PRUint32& aFlags);

Просмотреть файл

@ -165,9 +165,10 @@ nsPopupBoxObject::SizeTo(PRInt32 aWidth, PRInt32 aHeight)
nsAutoString width, height;
width.AppendInt(aWidth);
height.AppendInt(aHeight);
mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::width, width, PR_FALSE);
mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::height, height, PR_TRUE);
nsCOMPtr<nsIContent> content = mContent;
content->SetAttr(kNameSpaceID_None, nsHTMLAtoms::width, width, PR_FALSE);
content->SetAttr(kNameSpaceID_None, nsHTMLAtoms::height, height, PR_TRUE);
return NS_OK;
}

Просмотреть файл

@ -667,7 +667,7 @@ nsPopupSetFrame::OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
PRUint32 count = aPopupContent->GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
nsIContent *grandChild = aPopupContent->GetChildAt(i);
nsCOMPtr<nsIContent> grandChild = aPopupContent->GetChildAt(i);
if (grandChild->Tag() == nsXULAtoms::menuitem) {
// See if we have a command attribute.

Просмотреть файл

@ -98,6 +98,8 @@ nsProgressMeterFrame::AttributeChanged(PRInt32 aNameSpaceID,
if (!barChild) return NS_OK;
nsIFrame* remainderChild = barChild->GetNextSibling();
if (!remainderChild) return NS_OK;
nsCOMPtr<nsIContent> remainderContent = remainderChild->GetContent();
if (!remainderContent) return NS_OK;
nsAutoString value;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::value, value);
@ -112,11 +114,14 @@ nsProgressMeterFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsAutoString leftFlex, rightFlex;
leftFlex.AppendInt(flex);
rightFlex.AppendInt(remainder);
nsWeakFrame weakFrame(this);
barChild->GetContent()->SetAttr(kNameSpaceID_None, nsXULAtoms::flex, leftFlex, PR_TRUE);
remainderChild->GetContent()->SetAttr(kNameSpaceID_None, nsXULAtoms::flex, rightFlex, PR_TRUE);
remainderContent->SetAttr(kNameSpaceID_None, nsXULAtoms::flex, rightFlex, PR_TRUE);
nsBoxLayoutState state(GetPresContext());
MarkDirty(state);
if (weakFrame.IsAlive()) {
nsBoxLayoutState state(GetPresContext());
MarkDirty(state);
}
}
return NS_OK;
}

Просмотреть файл

@ -180,9 +180,12 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
return PR_FALSE;
}
// set this attribute so we can style it later
nsWeakFrame weakFrame(this);
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::active, NS_LITERAL_STRING("true"), PR_TRUE);
DoButtonAction(smoothScroll);
if (weakFrame.IsAlive()) {
DoButtonAction(smoothScroll);
}
if (repeat)
nsRepeatService::GetInstance()->Start(this);
return PR_TRUE;
@ -226,7 +229,7 @@ nsScrollbarButtonFrame::DoButtonAction(PRBool aSmoothScroll)
return;
// get the scrollbars content node
nsIContent* content = scrollbar->GetContent();
nsCOMPtr<nsIContent> content = scrollbar->GetContent();
// get the current pos
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);

Просмотреть файл

@ -564,12 +564,13 @@ nsSplitterFrameInner::MouseDrag(nsPresContext* aPresContext, nsGUIEvent* aEvent)
//printf("Collapse right\n");
if (supportsAfter)
{
mOuter->mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::substate,
NS_LITERAL_STRING("after"),
PR_TRUE);
mOuter->mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::state,
NS_LITERAL_STRING("collapsed"),
PR_TRUE);
nsCOMPtr<nsIContent> outer = mOuter->mContent;
outer->SetAttr(kNameSpaceID_None, nsXULAtoms::substate,
NS_LITERAL_STRING("after"),
PR_TRUE);
outer->SetAttr(kNameSpaceID_None, nsXULAtoms::state,
NS_LITERAL_STRING("collapsed"),
PR_TRUE);
}
} else if (oldPos < 0 && oldPos < pos)
@ -577,12 +578,13 @@ nsSplitterFrameInner::MouseDrag(nsPresContext* aPresContext, nsGUIEvent* aEvent)
//printf("Collapse left\n");
if (supportsBefore)
{
mOuter->mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::substate,
NS_LITERAL_STRING("before"),
PR_TRUE);
mOuter->mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::state,
NS_LITERAL_STRING("collapsed"),
PR_TRUE);
nsCOMPtr<nsIContent> outer = mOuter->mContent;
outer->SetAttr(kNameSpaceID_None, nsXULAtoms::substate,
NS_LITERAL_STRING("before"),
PR_TRUE);
outer->SetAttr(kNameSpaceID_None, nsXULAtoms::state,
NS_LITERAL_STRING("collapsed"),
PR_TRUE);
}
}
}
@ -962,7 +964,7 @@ nsSplitterFrameInner::UpdateState()
(newState == CollapsedBefore ||
mState == CollapsedBefore));
if (splitterSibling) {
nsIContent* sibling = splitterSibling->GetContent();
nsCOMPtr<nsIContent> sibling = splitterSibling->GetContent();
if (sibling) {
if (mState == CollapsedBefore || mState == CollapsedAfter) {
// CollapsedBefore -> Open
@ -1108,7 +1110,9 @@ nsSplitterFrameInner::SetPreferredSize(nsBoxLayoutState& aState, nsIBox* aChildB
prefValue, eCaseMatters))
return;
nsWeakFrame weakBox(aChildBox);
content->SetAttr(kNameSpaceID_None, attribute, prefValue, PR_TRUE);
ENSURE_TRUE(weakBox.IsAlive());
aChildBox->MarkDirty(aState);
}

Просмотреть файл

@ -800,6 +800,9 @@ nsTreeBodyFrame::UpdateScrollbars(const ScrollParts& aParts)
float t2p = GetPresContext()->TwipsToPixels();
nscoord rowHeightAsPixels = NSToCoordRound((float)mRowHeight*t2p);
// Keep strong ref.
nsCOMPtr<nsIContent> hScroll = aParts.mHScrollbarContent;
if (aParts.mVScrollbar) {
nsAutoString curPos;
curPos.AppendInt(mTopRowIndex*rowHeightAsPixels);
@ -809,7 +812,7 @@ nsTreeBodyFrame::UpdateScrollbars(const ScrollParts& aParts)
if (aParts.mHScrollbar) {
nsAutoString curPos;
curPos.AppendInt(mHorzPosition);
aParts.mHScrollbarContent->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
hScroll->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
}
}
@ -877,12 +880,13 @@ nsTreeBodyFrame::InvalidateScrollbars(const ScrollParts& aParts)
{
if (mUpdateBatchNest || !mView)
return;
nsWeakFrame weakFrame(this);
nsPresContext* presContext = GetPresContext();
nsCOMPtr<nsIContent> vScrollbar = aParts.mVScrollbarContent;
nsCOMPtr<nsIContent> hScrollbar = aParts.mHScrollbarContent;
if (aParts.mVScrollbar) {
// Do Vertical Scrollbar
nsIContent* scrollbar = aParts.mVScrollbarContent;
nsAutoString maxposStr;
float t2p = presContext->TwipsToPixels();
@ -890,31 +894,34 @@ nsTreeBodyFrame::InvalidateScrollbars(const ScrollParts& aParts)
PRInt32 size = rowHeightAsPixels * (mRowCount > mPageLength ? mRowCount - mPageLength : 0);
maxposStr.AppendInt(size);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
vScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
// Also set our page increment and decrement.
nscoord pageincrement = mPageLength*rowHeightAsPixels;
nsAutoString pageStr;
pageStr.AppendInt(pageincrement);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
vScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
}
if (aParts.mHScrollbar && aParts.mColumnsScrollableView) {
// And now Horizontal scrollbar
nsRect bounds = aParts.mColumnsScrollableView->View()->GetBounds();
nsIContent* scrollbar = aParts.mHScrollbarContent;
nsAutoString maxposStr;
maxposStr.AppendInt(mHorzWidth > bounds.width ? mHorzWidth - bounds.width : 0);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
hScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
nsAutoString pageStr;
pageStr.AppendInt(bounds.width);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
hScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
ENSURE_TRUE(weakFrame.IsAlive());
pageStr.Truncate();
pageStr.AppendInt(NSIntPixelsToTwips(16, presContext->PixelsToTwips()));
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::increment, pageStr, PR_TRUE);
hScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::increment, pageStr, PR_TRUE);
}
}
@ -3835,7 +3842,7 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition
PRInt32 delta = aPosition - mHorzPosition;
mHorzPosition = aPosition;
nsPresContext* presContext = GetPresContext();
nsRefPtr<nsPresContext> presContext = GetPresContext();
float t2p = presContext->TwipsToPixels();
// See if we have a background image. If we do, then we cannot blit.
@ -3853,9 +3860,10 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition
// Reflect the change in the scrollbar
nsAutoString curPos;
curPos.AppendInt(aPosition);
nsWeakFrame weakFrame(this);
aParts.mHScrollbarContent->SetAttr(kNameSpaceID_None,
nsXULAtoms::curpos, curPos, PR_TRUE);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
// Update the column scroll view
aParts.mColumnsScrollableView->ScrollTo(mHorzPosition, 0, 0);
@ -3881,6 +3889,7 @@ nsTreeBodyFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldInd
ScrollParts parts = GetScrollParts();
nsWeakFrame weakFrame(this);
if (sf == parts.mVScrollbar) {
if (aNewIndex > aOldIndex)
ScrollToRowInternal(parts, mTopRowIndex+1);
@ -3890,6 +3899,7 @@ nsTreeBodyFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldInd
ScrollHorzInternal(parts, aNewIndex);
}
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
UpdateScrollbars(parts);
return NS_OK;
@ -3915,7 +3925,9 @@ nsTreeBodyFrame::PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, PRI
nscoord rh = NSToCoordRound((float)mRowHeight*t2p);
nscoord newrow = aNewIndex/rh;
nsWeakFrame weakFrame(this);
ScrollInternal(parts, newrow);
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
// Go exactly where we're supposed to
// Update the scrollbar.

Просмотреть файл

@ -137,13 +137,13 @@ nsTreeUtils::UpdateSortIndicators(nsIContent* aColumn, const nsAString& aDirecti
aColumn->SetAttr(kNameSpaceID_None, nsXULAtoms::sortActive, NS_LITERAL_STRING("true"), PR_TRUE);
// Unset sort attribute(s) on the other columns
nsIContent* parentContent = aColumn->GetParent();
nsCOMPtr<nsIContent> parentContent = aColumn->GetParent();
if (parentContent &&
parentContent->NodeInfo()->Equals(nsXULAtoms::treecols,
kNameSpaceID_XUL)) {
PRUint32 i, numChildren = parentContent->GetChildCount();
for (i = 0; i < numChildren; ++i) {
nsIContent *childContent = parentContent->GetChildAt(i);
nsCOMPtr<nsIContent> childContent = parentContent->GetChildAt(i);
if (childContent &&
childContent != aColumn &&