зеркало из https://github.com/mozilla/pjs.git
Changing XUL menus to use a :-moz-menuactive pseudoclass rather than a menuactive attribute for styling the active item. This will allow XBL select widgets to not modify the HTML DOM. Bug 128947, r=dbaron, sr=hyatt, a=asa.
This commit is contained in:
Родитель
3332aea218
Коммит
f0da73b96a
|
@ -42,6 +42,7 @@
|
|||
#include "nsIAccessible.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#include "nsIDOMXULMenuBarElement.h"
|
||||
|
||||
// ------------------------ Menu Item -----------------------------
|
||||
|
||||
|
@ -58,10 +59,22 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetAccState(PRUint32 *_retval)
|
|||
// Focused?
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
|
||||
NS_ASSERTION(element, "No DOM element for menu node!");
|
||||
PRBool isFocused = PR_FALSE;
|
||||
element->HasAttribute(NS_LITERAL_STRING("menuactive"), &isFocused);
|
||||
if (isFocused)
|
||||
*_retval |= STATE_FOCUSED;
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
mDOMNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
if (parentNode) {
|
||||
nsCOMPtr<nsIDOMElement> currentItem;
|
||||
nsCOMPtr<nsIDOMXULPopupElement> popupEl = do_QueryInterface(parentNode);
|
||||
if (popupEl)
|
||||
popupEl->GetActiveItem(getter_AddRefs(currentItem));
|
||||
else {
|
||||
nsCOMPtr<nsIDOMXULMenuBarElement> menubar = do_QueryInterface(parentNode);
|
||||
if (menubar)
|
||||
menubar->GetActiveMenu(getter_AddRefs(currentItem));
|
||||
}
|
||||
|
||||
if (currentItem == element)
|
||||
*_retval |= STATE_FOCUSED;
|
||||
}
|
||||
|
||||
// Has Popup?
|
||||
nsAutoString tagName;
|
||||
|
|
|
@ -93,6 +93,7 @@ struct RuleProcessorData {
|
|||
PRPackedBool mIsQuirkMode; // Possibly remove use of this in SelectorMatches?
|
||||
PRPackedBool mHasAttributes; // if content, content->GetAttrCount() > 0
|
||||
PRPackedBool mIsChecked; // checked/selected attribute for option and select elements
|
||||
PRPackedBool mIsMenuActive; // menuactive state for options/menus/menuitems
|
||||
nsLinkState mLinkState; // if a link, this is the state, otherwise unknown
|
||||
PRInt32 mEventState; // if content, eventStateMgr->GetContentState()
|
||||
PRInt32 mNameSpaceID; // if content, content->GetNameSapce()
|
||||
|
|
|
@ -1557,6 +1557,7 @@ static PRBool IsPseudoClass(const nsIAtom* aAtom)
|
|||
(nsCSSAtoms::lastChildPseudo == aAtom) ||
|
||||
(nsCSSAtoms::lastNodePseudo == aAtom) ||
|
||||
(nsCSSAtoms::linkPseudo == aAtom) ||
|
||||
(nsCSSAtoms::menuActivePseudo == aAtom) ||
|
||||
(nsCSSAtoms::rootPseudo == aAtom) ||
|
||||
(nsCSSAtoms::xblBoundElementPseudo == aAtom) ||
|
||||
(nsCSSAtoms::visitedPseudo == aAtom));
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
#include "nsQuickSort.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULContent.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#include "nsIDOMXULMenuBarElement.h"
|
||||
#include "nsXULAtoms.h"
|
||||
#endif
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -3234,6 +3237,7 @@ RuleProcessorData::RuleProcessorData(nsIPresContext* aPresContext,
|
|||
mIsHTMLLink = PR_FALSE;
|
||||
mIsSimpleXLink = PR_FALSE;
|
||||
mIsChecked = PR_FALSE;
|
||||
mIsMenuActive = PR_FALSE;
|
||||
mLinkState = eLinkState_Unknown;
|
||||
mEventState = NS_EVENT_STATE_UNSPECIFIED;
|
||||
mNameSpaceID = kNameSpaceID_Unknown;
|
||||
|
@ -3302,14 +3306,39 @@ RuleProcessorData::RuleProcessorData(nsIPresContext* aPresContext,
|
|||
mIsSimpleXLink = PR_TRUE;
|
||||
}
|
||||
|
||||
// The :checked pseudoclass applies to input and option elements
|
||||
if (mIsHTMLContent) {
|
||||
PRBool isChecked = PR_FALSE;
|
||||
if (mContentTag == nsHTMLAtoms::option) {
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> optEl = do_QueryInterface(mContent);
|
||||
optEl->GetSelected(&isChecked);
|
||||
}
|
||||
|
||||
mIsChecked = isChecked;
|
||||
}
|
||||
|
||||
// The :-moz-menuactive pseudoclass applies to HTML option elements,
|
||||
// XUL menuitem elements, and XUL menu elements.
|
||||
if ((mIsHTMLContent && mContentTag == nsHTMLAtoms::option) ||
|
||||
(mContent->IsContentOfType(nsIContent::eXUL) &&
|
||||
(mContentTag == nsXULAtoms::menuitem || mContentTag == nsXULAtoms::menu))) {
|
||||
|
||||
nsCOMPtr<nsIDOMElement> currentItem;
|
||||
nsCOMPtr<nsIDOMXULPopupElement> popupEl = do_QueryInterface(mParentContent);
|
||||
if (popupEl)
|
||||
popupEl->GetActiveItem(getter_AddRefs(currentItem));
|
||||
else {
|
||||
nsCOMPtr<nsIDOMXULMenuBarElement> menubar = do_QueryInterface(mParentContent);
|
||||
if (menubar)
|
||||
menubar->GetActiveMenu(getter_AddRefs(currentItem));
|
||||
}
|
||||
|
||||
if (currentItem) {
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mContent);
|
||||
if (currentItem == element)
|
||||
mIsMenuActive = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3609,6 +3638,12 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
if (aTestState)
|
||||
result = data.mIsChecked ? localTrue : localFalse;
|
||||
}
|
||||
else if (nsCSSAtoms::menuActivePseudo == pseudoClass->mAtom) {
|
||||
// This pseudoclass will match on at most one child of
|
||||
// a menupopup.
|
||||
if (aTestState)
|
||||
result = data.mIsMenuActive ? localTrue : localFalse;
|
||||
}
|
||||
else {
|
||||
result = localFalse; // unknown pseudo class
|
||||
}
|
||||
|
@ -4242,6 +4277,7 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
|||
(pseudoClass->mAtom == nsCSSAtoms::focusPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::hoverPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::linkPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::menuActivePseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::selectionPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::visitedPseudo)) {
|
||||
return PR_TRUE;
|
||||
|
|
|
@ -85,6 +85,7 @@ CSS_ATOM(langPseudo, ":lang")
|
|||
CSS_ATOM(linkPseudo, ":link")
|
||||
|
||||
CSS_ATOM(menuPseudo, ":menu")
|
||||
CSS_ATOM(menuActivePseudo, ":-moz-menuactive");
|
||||
|
||||
CSS_ATOM(notPseudo, ":not")
|
||||
|
||||
|
|
|
@ -815,6 +815,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIDOMXULMenuBarElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -892,6 +899,11 @@
|
|||
<PATH>nsIDOMXULPopupElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIDOMXULMenuBarElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
|
@ -1656,6 +1668,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIDOMXULMenuBarElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -1733,6 +1752,11 @@
|
|||
<PATH>nsIDOMXULPopupElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIDOMXULMenuBarElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
</TARGETLIST>
|
||||
|
@ -1821,6 +1845,12 @@
|
|||
<PATH>nsIDOMXULPopupElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIDOMXULMenuBarElement.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
nsIDOMXULCommandDispatcher.idl
|
||||
nsIDOMXULDocument.idl
|
||||
nsIDOMXULElement.idl
|
||||
nsIDOMXULMenuBarElement.idl
|
||||
|
|
|
@ -45,6 +45,7 @@ XPIDLSRCS = \
|
|||
nsIDOMXULSelectCntrlEl.idl \
|
||||
nsIDOMXULSelectCntrlItemEl.idl \
|
||||
nsIDOMXULMultSelectCntrlEl.idl \
|
||||
nsIDOMXULMenuBarElement.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -41,6 +41,7 @@ XPIDLSRCS = \
|
|||
.\nsIDOMXULSelectCntrlEl.idl \
|
||||
.\nsIDOMXULSelectCntrlItemEl.idl \
|
||||
.\nsIDOMXULMultSelectCntrlEl.idl \
|
||||
.\nsIDOMXULMenuBarElement.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
|
|
@ -54,7 +54,8 @@ interface nsIDOMXULPopupElement : nsIDOMXULElement {
|
|||
const unsigned short AFTER_POINTER = 11;
|
||||
|
||||
attribute DOMString position;
|
||||
|
||||
attribute nsIDOMElement activeItem;
|
||||
|
||||
void showPopup(in unsigned short alignment,
|
||||
in nsIDOMElement target,
|
||||
in nsIDOMElement anchor);
|
||||
|
|
|
@ -1557,6 +1557,7 @@ static PRBool IsPseudoClass(const nsIAtom* aAtom)
|
|||
(nsCSSAtoms::lastChildPseudo == aAtom) ||
|
||||
(nsCSSAtoms::lastNodePseudo == aAtom) ||
|
||||
(nsCSSAtoms::linkPseudo == aAtom) ||
|
||||
(nsCSSAtoms::menuActivePseudo == aAtom) ||
|
||||
(nsCSSAtoms::rootPseudo == aAtom) ||
|
||||
(nsCSSAtoms::xblBoundElementPseudo == aAtom) ||
|
||||
(nsCSSAtoms::visitedPseudo == aAtom));
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
#include "nsQuickSort.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULContent.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#include "nsIDOMXULMenuBarElement.h"
|
||||
#include "nsXULAtoms.h"
|
||||
#endif
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -3234,6 +3237,7 @@ RuleProcessorData::RuleProcessorData(nsIPresContext* aPresContext,
|
|||
mIsHTMLLink = PR_FALSE;
|
||||
mIsSimpleXLink = PR_FALSE;
|
||||
mIsChecked = PR_FALSE;
|
||||
mIsMenuActive = PR_FALSE;
|
||||
mLinkState = eLinkState_Unknown;
|
||||
mEventState = NS_EVENT_STATE_UNSPECIFIED;
|
||||
mNameSpaceID = kNameSpaceID_Unknown;
|
||||
|
@ -3302,14 +3306,39 @@ RuleProcessorData::RuleProcessorData(nsIPresContext* aPresContext,
|
|||
mIsSimpleXLink = PR_TRUE;
|
||||
}
|
||||
|
||||
// The :checked pseudoclass applies to input and option elements
|
||||
if (mIsHTMLContent) {
|
||||
PRBool isChecked = PR_FALSE;
|
||||
if (mContentTag == nsHTMLAtoms::option) {
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> optEl = do_QueryInterface(mContent);
|
||||
optEl->GetSelected(&isChecked);
|
||||
}
|
||||
|
||||
mIsChecked = isChecked;
|
||||
}
|
||||
|
||||
// The :-moz-menuactive pseudoclass applies to HTML option elements,
|
||||
// XUL menuitem elements, and XUL menu elements.
|
||||
if ((mIsHTMLContent && mContentTag == nsHTMLAtoms::option) ||
|
||||
(mContent->IsContentOfType(nsIContent::eXUL) &&
|
||||
(mContentTag == nsXULAtoms::menuitem || mContentTag == nsXULAtoms::menu))) {
|
||||
|
||||
nsCOMPtr<nsIDOMElement> currentItem;
|
||||
nsCOMPtr<nsIDOMXULPopupElement> popupEl = do_QueryInterface(mParentContent);
|
||||
if (popupEl)
|
||||
popupEl->GetActiveItem(getter_AddRefs(currentItem));
|
||||
else {
|
||||
nsCOMPtr<nsIDOMXULMenuBarElement> menubar = do_QueryInterface(mParentContent);
|
||||
if (menubar)
|
||||
menubar->GetActiveMenu(getter_AddRefs(currentItem));
|
||||
}
|
||||
|
||||
if (currentItem) {
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mContent);
|
||||
if (currentItem == element)
|
||||
mIsMenuActive = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3609,6 +3638,12 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
if (aTestState)
|
||||
result = data.mIsChecked ? localTrue : localFalse;
|
||||
}
|
||||
else if (nsCSSAtoms::menuActivePseudo == pseudoClass->mAtom) {
|
||||
// This pseudoclass will match on at most one child of
|
||||
// a menupopup.
|
||||
if (aTestState)
|
||||
result = data.mIsMenuActive ? localTrue : localFalse;
|
||||
}
|
||||
else {
|
||||
result = localFalse; // unknown pseudo class
|
||||
}
|
||||
|
@ -4242,6 +4277,7 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
|||
(pseudoClass->mAtom == nsCSSAtoms::focusPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::hoverPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::linkPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::menuActivePseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::selectionPseudo) ||
|
||||
(pseudoClass->mAtom == nsCSSAtoms::visitedPseudo)) {
|
||||
return PR_TRUE;
|
||||
|
|
|
@ -93,6 +93,7 @@ struct RuleProcessorData {
|
|||
PRPackedBool mIsQuirkMode; // Possibly remove use of this in SelectorMatches?
|
||||
PRPackedBool mHasAttributes; // if content, content->GetAttrCount() > 0
|
||||
PRPackedBool mIsChecked; // checked/selected attribute for option and select elements
|
||||
PRPackedBool mIsMenuActive; // menuactive state for options/menus/menuitems
|
||||
nsLinkState mLinkState; // if a link, this is the state, otherwise unknown
|
||||
PRInt32 mEventState; // if content, eventStateMgr->GetContentState()
|
||||
PRInt32 mNameSpaceID; // if content, content->GetNameSapce()
|
||||
|
|
|
@ -84,6 +84,8 @@ public:
|
|||
|
||||
NS_IMETHOD GetActiveChild(nsIDOMElement** aResult)=0;
|
||||
NS_IMETHOD SetActiveChild(nsIDOMElement* aChild)=0;
|
||||
|
||||
NS_IMETHOD NotifyStateChanged(nsIMenuFrame* aOtherMenuFrame) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "nsMenuPopupFrame.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIDOMXULMenuBarElement.h"
|
||||
#ifdef XP_WIN
|
||||
#include "nsISound.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
@ -172,7 +173,7 @@ nsMenuBarFrame::IsOpen()
|
|||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
if (isOpen) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -199,6 +200,8 @@ nsMenuBarFrame::SetActive(PRBool aActiveFlag)
|
|||
void
|
||||
nsMenuBarFrame::ToggleMenuActiveState()
|
||||
{
|
||||
nsIMenuFrame* oldCurrent = mCurrentMenu;
|
||||
|
||||
if (mIsActive) {
|
||||
// Deactivate the menu bar
|
||||
mIsActive = PR_FALSE;
|
||||
|
@ -221,7 +224,7 @@ nsMenuBarFrame::ToggleMenuActiveState()
|
|||
InstallKeyboardNavigator();
|
||||
|
||||
// Set the active menu to be the top left item (e.g., the File menu).
|
||||
// We use an attribute called "menuactive" to track the current active menu.
|
||||
// We use the -moz-menuactive pseudoclass to track the current active menu.
|
||||
nsIMenuFrame* firstFrame;
|
||||
GetNextMenuItem(nsnull, &firstFrame);
|
||||
if (firstFrame) {
|
||||
|
@ -231,6 +234,25 @@ nsMenuBarFrame::ToggleMenuActiveState()
|
|||
mCurrentMenu = firstFrame;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the state on the menubar content node
|
||||
nsCOMPtr<nsIDOMXULMenuBarElement> menubar = do_QueryInterface(mContent);
|
||||
nsCOMPtr<nsIDOMElement> newActive;
|
||||
if (mCurrentMenu) {
|
||||
nsIFrame* frame = nsnull;
|
||||
CallQueryInterface(mCurrentMenu, &frame);
|
||||
nsCOMPtr<nsIContent> content;
|
||||
frame->GetContent(getter_AddRefs(content));
|
||||
newActive = do_QueryInterface(content);
|
||||
}
|
||||
menubar->SetActiveMenu(newActive);
|
||||
|
||||
// Now send a CSS state change notification
|
||||
if (mCurrentMenu)
|
||||
mCurrentMenu->NotifyStateChanged(oldCurrent);
|
||||
else if (oldCurrent)
|
||||
oldCurrent->NotifyStateChanged(nsnull);
|
||||
|
||||
}
|
||||
|
||||
static void GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame* aChild,
|
||||
|
@ -515,6 +537,8 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
PRBool wasOpen = PR_FALSE;
|
||||
|
||||
// Unset the current child.
|
||||
nsIMenuFrame* oldMenuFrame = mCurrentMenu;
|
||||
|
||||
if (mCurrentMenu) {
|
||||
mCurrentMenu->MenuIsOpen(wasOpen);
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
|
@ -533,6 +557,25 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
|
||||
mCurrentMenu = aMenuItem;
|
||||
|
||||
// Update the menubar content node
|
||||
nsCOMPtr<nsIDOMXULMenuBarElement> menubar = do_QueryInterface(mContent);
|
||||
nsCOMPtr<nsIDOMElement> newActive;
|
||||
if (mCurrentMenu) {
|
||||
nsIFrame* frame = nsnull;
|
||||
CallQueryInterface(mCurrentMenu, &frame);
|
||||
nsCOMPtr<nsIContent> content;
|
||||
frame->GetContent(getter_AddRefs(content));
|
||||
newActive = do_QueryInterface(content);
|
||||
}
|
||||
|
||||
menubar->SetActiveMenu(newActive);
|
||||
|
||||
// Now send a CSS state change notification
|
||||
if (mCurrentMenu)
|
||||
mCurrentMenu->NotifyStateChanged(oldMenuFrame);
|
||||
else if (oldMenuFrame)
|
||||
oldMenuFrame->NotifyStateChanged(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "nsGUIEvent.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsCSSAtoms.h"
|
||||
|
||||
#define NS_MENU_POPUP_LIST_INDEX 0
|
||||
|
||||
|
@ -583,14 +584,10 @@ nsMenuFrame::SelectMenu(PRBool aActivateFlag)
|
|||
nsAutoString domEventToFire;
|
||||
|
||||
if (aActivateFlag) {
|
||||
// Highlight the menu.
|
||||
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
// The menuactivated event is used by accessibility to track the user's movements through menus
|
||||
domEventToFire.Assign(NS_LITERAL_STRING("DOMMenuItemActive"));
|
||||
}
|
||||
else {
|
||||
// Unhighlight the menu.
|
||||
mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE);
|
||||
domEventToFire.Assign(NS_LITERAL_STRING("DOMMenuItemInactive"));
|
||||
}
|
||||
|
||||
|
@ -1307,9 +1304,9 @@ nsMenuFrame::Notify(nsITimer* aTimer)
|
|||
// Our timer has fired.
|
||||
if (aTimer == mOpenTimer.get()) {
|
||||
if (!mMenuOpen && mMenuParent) {
|
||||
nsAutoString active;
|
||||
mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, active);
|
||||
if (active.Equals(NS_LITERAL_STRING("true"))) {
|
||||
nsIMenuFrame* activeMenu = nsnull;
|
||||
mMenuParent->GetCurrentMenuItem(&activeMenu);
|
||||
if (activeMenu == this) {
|
||||
// We're still the active menu. Make sure all submenus/timers are closed
|
||||
// before opening this one
|
||||
mMenuParent->KillPendingTimers();
|
||||
|
@ -2094,6 +2091,24 @@ nsMenuFrame::GetScrollableView(nsIScrollableView** aView)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuFrame::NotifyStateChanged(nsIMenuFrame* aOtherMenuFrame)
|
||||
{
|
||||
nsCOMPtr<nsIContent> otherContent;
|
||||
if (aOtherMenuFrame) {
|
||||
nsIFrame* otherFrame = nsnull;
|
||||
CallQueryInterface(aOtherMenuFrame, &otherFrame);
|
||||
otherFrame->GetContent(getter_AddRefs(otherContent));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
mContent->GetDocument(*getter_AddRefs(document));
|
||||
if (document)
|
||||
document->ContentStatesChanged(mContent, otherContent, nsCSSAtoms::menuActivePseudo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Need to figure out what this does.
|
||||
NS_IMETHODIMP
|
||||
nsMenuFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)
|
||||
|
|
|
@ -167,6 +167,8 @@ public:
|
|||
NS_IMETHOD MarkChildrenStyleChange();
|
||||
NS_IMETHOD MarkAsGenerated();
|
||||
|
||||
NS_IMETHOD NotifyStateChanged(nsIMenuFrame* aOtherFrame);
|
||||
|
||||
// nsIScrollableViewProvider methods
|
||||
|
||||
NS_IMETHOD GetScrollableView(nsIScrollableView** aView);
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "nsIFrameManager.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIRootBox.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#ifdef XP_WIN
|
||||
#include "nsISound.h"
|
||||
#endif
|
||||
|
@ -1401,6 +1402,8 @@ NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
return NS_OK;
|
||||
|
||||
// Unset the current child.
|
||||
nsIMenuFrame* oldMenuFrame = nsnull;
|
||||
|
||||
if (mCurrentMenu) {
|
||||
PRBool isOpen = PR_FALSE;
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
|
@ -1423,6 +1426,8 @@ NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
mCloseTimer->Init(this, menuDelay, NS_PRIORITY_HIGHEST);
|
||||
mTimerMenu = mCurrentMenu;
|
||||
}
|
||||
|
||||
oldMenuFrame = mCurrentMenu;
|
||||
}
|
||||
|
||||
// Set the new child.
|
||||
|
@ -1433,6 +1438,24 @@ NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
|
||||
mCurrentMenu = aMenuItem;
|
||||
|
||||
// Update the content node's idea of the current item.
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (mCurrentMenu) {
|
||||
nsIFrame* frame = nsnull;
|
||||
CallQueryInterface(mCurrentMenu, &frame);
|
||||
frame->GetContent(getter_AddRefs(newContent));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMXULPopupElement> popupEl = do_QueryInterface(mContent);
|
||||
nsCOMPtr<nsIDOMElement> domEl = do_QueryInterface(newContent);
|
||||
popupEl->SetActiveItem(domEl);
|
||||
|
||||
// Send menuactive state notification.
|
||||
if (mCurrentMenu)
|
||||
mCurrentMenu->NotifyStateChanged(oldMenuFrame);
|
||||
else if (oldMenuFrame)
|
||||
oldMenuFrame->NotifyStateChanged(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1846,6 +1869,11 @@ nsMenuPopupFrame::HandleEvent(nsIPresContext* aPresContext,
|
|||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::Destroy(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Make sure the content node doesn't think we still have an active item.
|
||||
nsCOMPtr<nsIDOMXULPopupElement> popupEl = do_QueryInterface(mContent);
|
||||
if (popupEl)
|
||||
popupEl->SetActiveItem(nsnull);
|
||||
|
||||
return nsBoxFrame::Destroy(aPresContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ menuitem[default="true"] {
|
|||
|
||||
menu[disabled="true"],
|
||||
menuitem[disabled="true"],
|
||||
menu[menuactive="true"][disabled="true"],
|
||||
menuitem[menuactive="true"][disabled="true"] {
|
||||
menu[disabled="true"]:-moz-menuactive,
|
||||
menuitem[disabled="true"]:-moz-menuactive {
|
||||
background-color: transparent !important;
|
||||
color: GrayText !important;
|
||||
}
|
||||
|
@ -92,11 +92,11 @@ menuitem[menuactive="true"][disabled="true"] {
|
|||
}
|
||||
|
||||
.menu-right[disabled="true"],
|
||||
.menu-right[menuactive="true"][disabled="true"] {
|
||||
menu:-moz-menuactive > .menu-right[disabled="true"] {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-arrow-dis.gif);
|
||||
}
|
||||
|
||||
.menu-right[menuactive="true"] {
|
||||
menu:-moz-menuactive > .menu-right {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-arrow-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,14 @@ menubar > menu {
|
|||
margin: 1px 0px 1px 0px;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"] {
|
||||
menubar > menu:-moz-menuactive {
|
||||
border-top: 1px solid ThreeDHighlight;
|
||||
border-right: 1px solid ThreeDShadow;
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
border-left: 1px solid ThreeDHighlight;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"][open="true"] {
|
||||
menubar > menu[open="true"]:-moz-menuactive {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
border-right: 1px solid ThreeDHighlight;
|
||||
border-bottom: 1px solid ThreeDHighlight;
|
||||
|
@ -144,10 +144,10 @@ popup > menuitem {
|
|||
max-width: 42em;
|
||||
}
|
||||
|
||||
menupopup > menu[menuactive="true"],
|
||||
menupopup > menuitem[menuactive="true"],
|
||||
popup > menu[menuactive="true"],
|
||||
popup > menuitem[menuactive="true"] {
|
||||
menupopup > menu:-moz-menuactive,
|
||||
menupopup > menuitem:-moz-menuactive,
|
||||
popup > menu:-moz-menuactive,
|
||||
popup > menuitem:-moz-menuactive {
|
||||
background-color: -moz-mac-menuselect;
|
||||
color: -moz-mac-menutextselect;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ menuitem[checked="true"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-check-dis.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][menuactive="true"] {
|
||||
menuitem[checked="true"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-check-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ menuitem[checked="true"][type="radio"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-radio.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][type="radio"][menuactive="true"] {
|
||||
menuitem[checked="true"][type="radio"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-radio-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,8 @@ menulist > menupopup > menuitem[selected="true"],
|
|||
list-style-image: url("chrome://global/skin/menu/menu-radio.gif");
|
||||
}
|
||||
|
||||
menulist > menupopup > menuitem[menuactive="true"][selected="true"],
|
||||
.menulist-menupopup > menuitem[menuactive="true"][selected="true"] {
|
||||
menulist > menupopup > menuitem[selected="true"]:-moz-menuactive,
|
||||
.menulist-menupopup > menuitem[selected="true"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-radio-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -227,4 +227,4 @@ menulist > menupopup > menuseparator,
|
|||
.treecell-popupcell-menu {
|
||||
margin-left: -2px;
|
||||
list-style-image: url("chrome://global/skin/columnselect.gif");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ menuitem[default="true"] {
|
|||
}
|
||||
|
||||
menu[disabled="true"], menuitem[disabled="true"],
|
||||
menu[menuactive="true"][disabled="true"],
|
||||
menuitem[menuactive="true"][disabled="true"] {
|
||||
menu[disabled="true"]:-moz-menuactive,
|
||||
menuitem[disabled="true"]:-moz-menuactive {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ menuitem[menuactive="true"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-arrow.gif");
|
||||
}
|
||||
|
||||
.menu-right[menuactive="true"] {
|
||||
menu:-moz-menuactive > .menu-right {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-arrow-hover.gif");
|
||||
}
|
||||
|
||||
|
@ -104,14 +104,14 @@ menubar > menu {
|
|||
margin: 1px 0px 1px 0px;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"] {
|
||||
menubar > menu:-moz-menuactive {
|
||||
border-top: 1px solid ThreeDHighlight;
|
||||
border-right: 1px solid ThreeDShadow;
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
border-left: 1px solid ThreeDHighlight;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"][open="true"] {
|
||||
menubar > menu[open="true"]:-moz-menuactive {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
border-right: 1px solid ThreeDHighlight;
|
||||
border-bottom: 1px solid ThreeDHighlight;
|
||||
|
@ -140,10 +140,10 @@ popup > menuitem {
|
|||
max-width: 42em;
|
||||
}
|
||||
|
||||
menupopup > menu[menuactive="true"],
|
||||
menupopup > menuitem[menuactive="true"],
|
||||
popup > menu[menuactive="true"],
|
||||
popup > menuitem[menuactive="true"] {
|
||||
menupopup > menu:-moz-menuactive,
|
||||
menupopup > menuitem:-moz-menuactive,
|
||||
popup > menu:-moz-menuactive,
|
||||
popup > menuitem:-moz-menuactive {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ menulist > menupopup > menu > .menu-iconic-left {
|
|||
display: none;
|
||||
}
|
||||
|
||||
menulist > menupopup > menuitem[menuactive="true"] {
|
||||
menulist > menupopup > menuitem:-moz-menuactive {
|
||||
border: 1px dotted #F5DB95;
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ menuitem[checked="true"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-check-disabled.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][menuactive="true"] {
|
||||
menuitem[checked="true"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-check-hover.gif");
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ menuitem[checked="true"][type="radio"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-radio-disabled.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][type="radio"][menuactive="true"] {
|
||||
menuitem[checked="true"][type="radio"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-radio-hover.gif");
|
||||
}
|
||||
|
||||
|
@ -227,4 +227,4 @@ menulist > menupopup > menuseparator,
|
|||
.treecell-popupcell-menu {
|
||||
margin-left: -2px;
|
||||
list-style-image: url("chrome://global/skin/columnselect.gif");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ menuitem[default="true"] {
|
|||
|
||||
menu[disabled="true"],
|
||||
menuitem[disabled="true"],
|
||||
menu[menuactive="true"][disabled="true"],
|
||||
menuitem[menuactive="true"][disabled="true"] {
|
||||
menu[disabled="true"]:-moz-menuactive,
|
||||
menuitem[disabled="true"]:-moz-menuactive {
|
||||
color: #838E9B;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ menuitem[menuactive="true"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-arrow.gif");
|
||||
}
|
||||
|
||||
.menu-right[menuactive="true"] {
|
||||
menu:-moz-menuactive > .menu-right {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-arrow-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -118,11 +118,11 @@ menubar > menu {
|
|||
margin: 1px 0px 1px 0px;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"] {
|
||||
menubar > menu:-moz-menuactive {
|
||||
border: 1px outset #DDE3EB;
|
||||
}
|
||||
|
||||
menubar > menu[menuactive="true"][open="true"] {
|
||||
menubar > menu[open="true"]:-moz-menuactive {
|
||||
border-style: inset;
|
||||
}
|
||||
|
||||
|
@ -148,10 +148,10 @@ popup > menuitem {
|
|||
max-width: 42em;
|
||||
}
|
||||
|
||||
menupopup > menu[menuactive="true"],
|
||||
menupopup > menuitem[menuactive="true"],
|
||||
popup > menu[menuactive="true"],
|
||||
popup > menuitem[menuactive="true"] {
|
||||
menupopup > menu:-moz-menuactive,
|
||||
menupopup > menuitem:-moz-menuactive,
|
||||
popup > menu:-moz-menuactive,
|
||||
popup > menuitem:-moz-menuactive {
|
||||
background-color: #424F63;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ menulist > menupopup > menuitem[selected="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-check.gif");
|
||||
}
|
||||
|
||||
menulist > menupopup > menuitem[menuactive="true"][selected="true"] {
|
||||
menulist > menupopup > menuitem[selected="true"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-check-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ menuitem[checked="true"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-check-dis.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][menuactive="true"] {
|
||||
menuitem[checked="true"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-check-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ menuitem[checked="true"][type="radio"][disabled="true"] {
|
|||
list-style-image: url("chrome://global/skin/menu/menu-radio-dis.gif");
|
||||
}
|
||||
|
||||
menuitem[checked="true"][type="radio"][menuactive="true"] {
|
||||
menuitem[checked="true"][type="radio"]:-moz-menuactive {
|
||||
list-style-image: url("chrome://global/skin/menu/menu-radio-hov.gif");
|
||||
}
|
||||
|
||||
|
@ -234,4 +234,4 @@ menulist > menupopup > menuseparator,
|
|||
.treecell-popupcell-menu {
|
||||
margin-left: -2px;
|
||||
list-style-image: url("chrome://global/skin/tree/columnpicker.gif");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<content>
|
||||
<xul:label class="menu-text" flex="1" inherits="value=label,accesskey,crop" crop="right"/>
|
||||
<xul:label class="menu-accel" inherits="value=acceltext"/>
|
||||
<xul:hbox align="center" class="menu-right" inherits="menuactive,disabled">
|
||||
<xul:hbox align="center" class="menu-right" inherits="disabled">
|
||||
<xul:image/>
|
||||
</xul:hbox>
|
||||
<children includes="menupopup"/>
|
||||
|
@ -71,7 +71,7 @@
|
|||
<binding id="menuitem-iconic" extends="chrome://global/content/bindings/menu.xml#menuitem-base">
|
||||
<content>
|
||||
<xul:hbox class="menu-iconic-left" align="center" pack="center"
|
||||
inherits="selected,menuactive,disabled,checked">
|
||||
inherits="selected,disabled,checked">
|
||||
<xul:image class="menu-iconic-icon" inherits="validate,src"/>
|
||||
</xul:hbox>
|
||||
<xul:label class="menu-iconic-text" flex="1" inherits="value=label,accesskey,crop" crop="right"/>
|
||||
|
@ -91,7 +91,7 @@
|
|||
</xul:hbox>
|
||||
<xul:label class="menu-iconic-text" flex="1" inherits="value=label,accesskey,crop" crop="right"/>
|
||||
<xul:label class="menu-iconic-accel" inherits="value=acceltext"/>
|
||||
<xul:hbox class="menu-right" inherits="menuactive,disabled" align="center" pack="center">
|
||||
<xul:hbox class="menu-right" inherits="disabled" align="center" pack="center">
|
||||
<xul:image/>
|
||||
</xul:hbox>
|
||||
<children includes="menupopup|template"/>
|
||||
|
@ -112,4 +112,4 @@
|
|||
|
||||
<binding id="menuseparator" extends="chrome://global/content/bindings/menu.xml#menuitem-base"/>
|
||||
|
||||
</bindings>
|
||||
</bindings>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
</content>
|
||||
|
||||
<implementation implements="nsIDOMXULPopupElement, nsIAccessibleProvider">
|
||||
<field name="activeItem"/>
|
||||
<property name="accessible">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
|
|
@ -177,7 +177,8 @@
|
|||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIAccessibleProvider">
|
||||
<implementation implements="nsIDOMXULMenuBarElement, nsIAccessibleProvider">
|
||||
<field name="activeMenu"/>
|
||||
<property name="accessible">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
|
Загрузка…
Ссылка в новой задаче