зеркало из https://github.com/mozilla/gecko-dev.git
Bug 348304, @nsMenuFrame::HandleEvent, r=enndeakin, sr=dbaron
This commit is contained in:
Родитель
895d3338c5
Коммит
4364552a81
|
@ -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 &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче