зеркало из https://github.com/mozilla/pjs.git
Bug 279703, backing out the popup changes due to performance regressions. sigh.
This commit is contained in:
Родитель
d6cdd07569
Коммит
74130084f7
|
@ -488,6 +488,7 @@ GK_ATOM(menugenerated, "menugenerated")
|
|||
GK_ATOM(menuitem, "menuitem")
|
||||
GK_ATOM(menulist, "menulist")
|
||||
GK_ATOM(menupopup, "menupopup")
|
||||
GK_ATOM(menutobedisplayed, "menutobedisplayed")
|
||||
GK_ATOM(message, "message")
|
||||
GK_ATOM(meta, "meta")
|
||||
GK_ATOM(method, "method")
|
||||
|
@ -519,7 +520,6 @@ GK_ATOM(never, "never")
|
|||
GK_ATOM(_new, "new")
|
||||
GK_ATOM(nextBidi, "NextBidi")
|
||||
GK_ATOM(no, "no")
|
||||
GK_ATOM(noautohide, "noautohide")
|
||||
GK_ATOM(nobr, "nobr")
|
||||
GK_ATOM(node, "node")
|
||||
GK_ATOM(nodeSet, "node-set")
|
||||
|
@ -634,7 +634,6 @@ GK_ATOM(pageincrement, "pageincrement")
|
|||
GK_ATOM(pagex, "pagex")
|
||||
GK_ATOM(pagey, "pagey")
|
||||
GK_ATOM(palettename, "palettename")
|
||||
GK_ATOM(panel, "panel")
|
||||
GK_ATOM(param, "param")
|
||||
GK_ATOM(parameter, "parameter")
|
||||
GK_ATOM(parent, "parent")
|
||||
|
@ -1391,15 +1390,12 @@ GK_ATOM(legendFrame, "LegendFrame")
|
|||
GK_ATOM(letterFrame, "LetterFrame")
|
||||
GK_ATOM(lineFrame, "LineFrame")
|
||||
GK_ATOM(listControlFrame,"ListControlFrame")
|
||||
GK_ATOM(menuBarFrame,"MenuBarFrame")
|
||||
GK_ATOM(menuFrame,"MenuFrame")
|
||||
GK_ATOM(menuPopupFrame,"MenuPopupFrame")
|
||||
GK_ATOM(objectFrame, "ObjectFrame")
|
||||
GK_ATOM(pageFrame, "PageFrame")
|
||||
GK_ATOM(pageBreakFrame, "PageBreakFrame")
|
||||
GK_ATOM(pageContentFrame, "PageContentFrame")
|
||||
GK_ATOM(placeholderFrame, "PlaceholderFrame")
|
||||
GK_ATOM(popupSetFrame, "PopupSetFrame")
|
||||
GK_ATOM(positionedInlineFrame, "PositionedInlineFrame")
|
||||
GK_ATOM(canvasFrame, "CanvasFrame")
|
||||
GK_ATOM(rootFrame, "RootFrame")
|
||||
|
|
|
@ -43,7 +43,7 @@ VPATH = @srcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = xul
|
||||
DIRS = src test
|
||||
DIRS = public src test
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
|
|
@ -39,53 +39,145 @@
|
|||
#ifndef nsIMenuParent_h___
|
||||
#define nsIMenuParent_h___
|
||||
|
||||
class nsMenuFrame;
|
||||
|
||||
// {33f700c8-976a-4cdb-8f6c-d9f4cfee8366}
|
||||
#define NS_IMENUPARENT_IID \
|
||||
{ 0x33f700c8, 0x976a, 0x4cdb, { 0x8f, 0x6c, 0xd9, 0xf4, 0xcf, 0xee, 0x83, 0x66 } }
|
||||
|
||||
class nsIMenuFrame;
|
||||
class nsIDOMKeyEvent;
|
||||
|
||||
/*
|
||||
* nsIMenuParent is an interface implemented by nsMenuBarFrame and nsMenuPopupFrame
|
||||
* as both serve as parent frames to nsMenuFrame.
|
||||
*
|
||||
* Don't implement this interface on other classes unless you also fix up references,
|
||||
* as this interface is directly cast to and from nsMenuBarFrame and nsMenuPopupFrame.
|
||||
* nsIMenuParent is implemented on frames and thus should not be
|
||||
* refcounted. Eventually it should not inherit from nsISupports.
|
||||
*/
|
||||
|
||||
class nsIMenuParent {
|
||||
/**
|
||||
* nsNavigationDirection: an enum expressing navigation through the menus in
|
||||
* terms which are independent of the directionality of the chrome. The
|
||||
* terminology, derived from XSL-FO and CSS3 (e.g.
|
||||
* http://www.w3.org/TR/css3-text/#TextLayout), is BASE (Before, After, Start,
|
||||
* End), with the addition of First and Last (mapped to Home and End
|
||||
* respectively).
|
||||
*
|
||||
* In languages such as English where the inline progression is left-to-right
|
||||
* and the block progression is top-to-bottom (lr-tb), these terms will map out
|
||||
* as in the following diagram
|
||||
*
|
||||
* --- inline progression --->
|
||||
*
|
||||
* First |
|
||||
* ... |
|
||||
* Before |
|
||||
* +--------+ block
|
||||
* Start | | End progression
|
||||
* +--------+ |
|
||||
* After |
|
||||
* ... |
|
||||
* Last V
|
||||
*
|
||||
*/
|
||||
|
||||
enum nsNavigationDirection {
|
||||
eNavigationDirection_Last,
|
||||
eNavigationDirection_First,
|
||||
eNavigationDirection_Start,
|
||||
eNavigationDirection_Before,
|
||||
eNavigationDirection_End,
|
||||
eNavigationDirection_After
|
||||
};
|
||||
|
||||
#define NS_DIRECTION_IS_INLINE(dir) (dir == eNavigationDirection_Start || \
|
||||
dir == eNavigationDirection_End)
|
||||
#define NS_DIRECTION_IS_BLOCK(dir) (dir == eNavigationDirection_Before || \
|
||||
dir == eNavigationDirection_After)
|
||||
#define NS_DIRECTION_IS_BLOCK_TO_EDGE(dir) (dir == eNavigationDirection_First || \
|
||||
dir == eNavigationDirection_Last)
|
||||
|
||||
/**
|
||||
* DirectionFromKeyCode_lr_tb: an array that maps keycodes to values of
|
||||
* nsNavigationDirection for left-to-right and top-to-bottom flow orientation
|
||||
*/
|
||||
static nsNavigationDirection DirectionFromKeyCode_lr_tb [6] = {
|
||||
eNavigationDirection_Last, // NS_VK_END
|
||||
eNavigationDirection_First, // NS_VK_HOME
|
||||
eNavigationDirection_Start, // NS_VK_LEFT
|
||||
eNavigationDirection_Before, // NS_VK_UP
|
||||
eNavigationDirection_End, // NS_VK_RIGHT
|
||||
eNavigationDirection_After // NS_VK_DOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* DirectionFromKeyCode_rl_tb: an array that maps keycodes to values of
|
||||
* nsNavigationDirection for right-to-left and top-to-bottom flow orientation
|
||||
*/
|
||||
static nsNavigationDirection DirectionFromKeyCode_rl_tb [6] = {
|
||||
eNavigationDirection_Last, // NS_VK_END
|
||||
eNavigationDirection_First, // NS_VK_HOME
|
||||
eNavigationDirection_End, // NS_VK_LEFT
|
||||
eNavigationDirection_Before, // NS_VK_UP
|
||||
eNavigationDirection_Start, // NS_VK_RIGHT
|
||||
eNavigationDirection_After // NS_VK_DOWN
|
||||
};
|
||||
|
||||
#ifdef IBMBIDI
|
||||
#define NS_DIRECTION_FROM_KEY_CODE(direction, keycode) \
|
||||
NS_ASSERTION(keycode >= NS_VK_END && keycode <= NS_VK_DOWN, \
|
||||
"Illegal key code"); \
|
||||
const nsStyleVisibility* vis = GetStyleVisibility(); \
|
||||
if (vis->mDirection == NS_STYLE_DIRECTION_RTL) \
|
||||
direction = DirectionFromKeyCode_rl_tb[keycode - NS_VK_END]; \
|
||||
else \
|
||||
direction = DirectionFromKeyCode_lr_tb[keycode - NS_VK_END];
|
||||
#else
|
||||
#define NS_DIRECTION_FROM_KEY_CODE(direction, keycode) \
|
||||
direction = DirectionFromKeyCode_lr_tb[keycode - NS_VK_END];
|
||||
#endif
|
||||
|
||||
class nsIMenuParent : public nsISupports {
|
||||
|
||||
public:
|
||||
// returns the menu frame of the currently active item within the menu
|
||||
virtual nsMenuFrame *GetCurrentMenuItem() = 0;
|
||||
// sets the currently active menu frame.
|
||||
NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) = 0;
|
||||
// indicate that the current menu frame is being destroyed, so clear the
|
||||
// current menu item
|
||||
virtual void CurrentMenuIsBeingDestroyed() = 0;
|
||||
// deselects the current item and closes its popup if any, then selects the
|
||||
// new item aMenuItem. For a menubar, if another menu is already open, the
|
||||
// new menu aMenuItem is opened. In this case, if aSelectFirstItem is true,
|
||||
// select the first item in it. For menupoups, the menu is not opened and
|
||||
// the aSelectFirstItem argument is not used.
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, PRBool aSelectFirstItem) = 0;
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMENUPARENT_IID)
|
||||
|
||||
// returns true if the menupopup is open. For menubars, returns false.
|
||||
virtual PRBool IsOpen() = 0;
|
||||
// returns true if the menubar is currently active. For menupopups, returns false.
|
||||
virtual PRBool IsActive() = 0;
|
||||
// returns true if this is a menubar. If false, it is a popup
|
||||
virtual PRBool IsMenuBar() = 0;
|
||||
// returns true if this is a menu, which has a tag of menupopup or popup.
|
||||
// Otherwise, this returns false
|
||||
virtual PRBool IsMenu() = 0;
|
||||
// returns true if this is a context menu
|
||||
virtual PRBool IsContextMenu() = 0;
|
||||
virtual nsIMenuFrame *GetCurrentMenuItem() = 0;
|
||||
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem) = 0;
|
||||
virtual nsIMenuFrame *GetNextMenuItem(nsIMenuFrame* aStart) = 0;
|
||||
virtual nsIMenuFrame *GetPreviousMenuItem(nsIMenuFrame* aStart) = 0;
|
||||
|
||||
// indicate that the menubar should become active or inactive
|
||||
NS_IMETHOD SetActive(PRBool aActiveFlag) = 0;
|
||||
NS_IMETHOD GetIsActive(PRBool& isActive) = 0;
|
||||
NS_IMETHOD GetWidget(nsIWidget **aWidget) = 0;
|
||||
|
||||
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) = 0;
|
||||
NS_IMETHOD ConsumeOutsideClicks(PRBool& aConsumeOutsideClicks) = 0;
|
||||
NS_IMETHOD ClearRecentlyRolledUp() = 0;
|
||||
NS_IMETHOD RecentlyRolledUp(nsIMenuFrame *aMenuFrame, PRBool *aJustRolledUp) = 0;
|
||||
|
||||
// notify that the menu has been closed and any active state should be
|
||||
// cleared. This should return true if the menu should be deselected
|
||||
// by the caller.
|
||||
virtual PRBool MenuClosed() = 0;
|
||||
NS_IMETHOD DismissChain() = 0;
|
||||
NS_IMETHOD HideChain() = 0;
|
||||
NS_IMETHOD KillPendingTimers() = 0;
|
||||
NS_IMETHOD CancelPendingTimers() = 0;
|
||||
|
||||
NS_IMETHOD AttachedDismissalListener() = 0;
|
||||
|
||||
NS_IMETHOD InstallKeyboardNavigator() = 0;
|
||||
NS_IMETHOD RemoveKeyboardNavigator() = 0;
|
||||
|
||||
// Used to move up, down, left, and right in menus.
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag) = 0;
|
||||
// Called when the ESC key is held down to close levels of menus.
|
||||
NS_IMETHOD Escape(PRBool& aHandledFlag) = 0;
|
||||
// Called to execute a menu item.
|
||||
NS_IMETHOD Enter() = 0;
|
||||
|
||||
NS_IMETHOD SetIsContextMenu(PRBool aIsContextMenu) = 0;
|
||||
NS_IMETHOD GetIsContextMenu(PRBool& aIsContextMenu) = 0;
|
||||
|
||||
NS_IMETHOD GetParentPopup(nsIMenuParent** aResult) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMenuParent, NS_IMENUPARENT_IID)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,14 +41,14 @@
|
|||
#define nsIRootBox_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
class nsPopupSetFrame;
|
||||
class nsIFrame;
|
||||
class nsIContent;
|
||||
class nsIPresShell;
|
||||
|
||||
// {9777EC2A-9A46-4D01-8CEB-B9CEB2C262A5}
|
||||
// {2256d568-3f5a-42ec-b932-3d0f78551a1a}
|
||||
#define NS_IROOTBOX_IID \
|
||||
{ 0x9777EC2A, 0x9A46, 0x4D01, \
|
||||
{ 0x8C, 0xEB, 0xB9, 0xCE, 0xB2, 0xC2, 0x62, 0xA5 } }
|
||||
{ 0x2256d568, 0x3f5a, 0x42ec, \
|
||||
{ 0xb9, 0x32, 0x3d, 0x0f, 0x78, 0x55, 0x1a, 0x1a } }
|
||||
|
||||
|
||||
class nsIRootBox : public nsISupports {
|
||||
|
@ -56,8 +56,8 @@ class nsIRootBox : public nsISupports {
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IROOTBOX_IID)
|
||||
|
||||
virtual nsPopupSetFrame* GetPopupSetFrame() = 0;
|
||||
virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) = 0;
|
||||
virtual nsIFrame* GetPopupSetFrame() = 0;
|
||||
virtual void SetPopupSetFrame(nsIFrame* aPopupSet)=0;
|
||||
|
||||
virtual nsIContent* GetDefaultTooltip() = 0;
|
||||
virtual void SetDefaultTooltip(nsIContent* aTooltip) = 0;
|
||||
|
|
|
@ -37,9 +37,11 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsMenuListener.h"
|
||||
#include "nsMenuBarFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -77,18 +79,51 @@ NS_NewMenuBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||
return new (aPresShell) nsMenuBarFrame (aPresShell, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsMenuBarFrame::AddRef(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsMenuBarFrame::Release(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
NS_INTERFACE_MAP_BEGIN(nsMenuBarFrame)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMenuParent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
||||
|
||||
|
||||
//
|
||||
// nsMenuBarFrame cntr
|
||||
//
|
||||
nsMenuBarFrame::nsMenuBarFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
||||
nsBoxFrame(aShell, aContext),
|
||||
mMenuBarListener(nsnull),
|
||||
mKeyboardNavigator(nsnull),
|
||||
mIsActive(PR_FALSE),
|
||||
mTarget(nsnull),
|
||||
mCaretWasVisible(PR_FALSE)
|
||||
{
|
||||
} // cntr
|
||||
|
||||
nsMenuBarFrame::~nsMenuBarFrame()
|
||||
{
|
||||
/* The menubar can still be active at this point under unusual circumstances.
|
||||
(say, while switching skins (which tears down all frames including
|
||||
this one) after having made a menu selection (say, Edit->Preferences,
|
||||
to get to the skin switching UI)). SetActive(PR_FALSE) releases
|
||||
mKeyboardNavigator, which is by now pointing to a deleted frame.
|
||||
*/
|
||||
SetActive(PR_FALSE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
|
@ -121,6 +156,20 @@ nsMenuBarFrame::Init(nsIContent* aContent,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::IsOpen()
|
||||
{
|
||||
PRBool isOpen = PR_FALSE;
|
||||
if(mCurrentMenu) {
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
if (isOpen) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::SetActive(PRBool aActiveFlag)
|
||||
{
|
||||
|
@ -128,15 +177,6 @@ nsMenuBarFrame::SetActive(PRBool aActiveFlag)
|
|||
if (mIsActive == aActiveFlag)
|
||||
return NS_OK;
|
||||
|
||||
if (!aActiveFlag) {
|
||||
// if there is a request to deactivate the menu bar, check to see whether
|
||||
// there is a menu popup open for the menu bar. In this case, don't
|
||||
// deactivate the menu bar.
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && pm->IsPopupOpenForMenuParent(this))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mIsActive = aActiveFlag;
|
||||
if (mIsActive) {
|
||||
InstallKeyboardNavigator();
|
||||
|
@ -199,22 +239,22 @@ nsMenuBarFrame::SetActive(PRBool aActiveFlag)
|
|||
NS_NAMED_LITERAL_STRING(active, "DOMMenuBarActive");
|
||||
NS_NAMED_LITERAL_STRING(inactive, "DOMMenuBarInactive");
|
||||
|
||||
FireDOMEvent(mIsActive ? active : inactive, mContent);
|
||||
FireDOMEventSynch(mIsActive ? active : inactive);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMenuFrame*
|
||||
void
|
||||
nsMenuBarFrame::ToggleMenuActiveState()
|
||||
{
|
||||
if (mIsActive) {
|
||||
// Deactivate the menu bar
|
||||
SetActive(PR_FALSE);
|
||||
if (mCurrentMenu) {
|
||||
nsMenuFrame* closeframe = mCurrentMenu;
|
||||
closeframe->SelectMenu(PR_FALSE);
|
||||
// Deactivate the menu.
|
||||
mCurrentMenu->OpenMenu(PR_FALSE);
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
mCurrentMenu = nsnull;
|
||||
return closeframe;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -228,7 +268,7 @@ nsMenuBarFrame::ToggleMenuActiveState()
|
|||
// 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.
|
||||
nsMenuFrame* firstFrame = nsXULPopupManager::GetNextMenuItem(this, nsnull, PR_FALSE);
|
||||
nsIMenuFrame* firstFrame = GetNextMenuItem(nsnull);
|
||||
if (firstFrame) {
|
||||
firstFrame->SelectMenu(PR_TRUE);
|
||||
|
||||
|
@ -236,13 +276,10 @@ nsMenuBarFrame::ToggleMenuActiveState()
|
|||
mCurrentMenu = firstFrame;
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static void
|
||||
GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame* aChild,
|
||||
nsIFrame** aResult)
|
||||
static void GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame* aChild,
|
||||
nsIFrame** aResult)
|
||||
{
|
||||
nsIContent* child = nsnull;
|
||||
if (aChild)
|
||||
|
@ -250,7 +287,7 @@ GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame* aChild,
|
|||
aShell->FrameConstructor()->GetInsertionPoint(aFrame, child, aResult);
|
||||
}
|
||||
|
||||
nsMenuFrame*
|
||||
nsIMenuFrame*
|
||||
nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
||||
{
|
||||
PRUint32 charCode;
|
||||
|
@ -268,7 +305,7 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
nsIContent* current = currFrame->GetContent();
|
||||
|
||||
// See if it's a menu item.
|
||||
if (nsXULPopupManager::IsValidMenuItem(PresContext(), current, PR_FALSE)) {
|
||||
if (IsValidItem(current)) {
|
||||
// Get the shortcut attribute.
|
||||
nsAutoString shortcutKey;
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, shortcutKey);
|
||||
|
@ -278,8 +315,11 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
if ( shortcutKey.Equals(Substring(&letter, &letter+1),
|
||||
nsCaseInsensitiveStringComparator()) ) {
|
||||
// We match!
|
||||
return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
|
||||
NS_STATIC_CAST(nsMenuFrame *, currFrame) : nsnull;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame))) {
|
||||
menuFrame = nsnull;
|
||||
}
|
||||
return menuFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,36 +335,263 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
soundInterface->Beep();
|
||||
}
|
||||
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->Rollup();
|
||||
|
||||
SetCurrentMenuItem(nsnull);
|
||||
SetActive(PR_FALSE);
|
||||
|
||||
DismissChain();
|
||||
#endif // #ifdef XP_WIN
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* virtual */ nsMenuFrame*
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag)
|
||||
{
|
||||
if (mCurrentMenu) {
|
||||
PRBool isOpen = PR_FALSE;
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
if (isOpen) {
|
||||
// No way this applies to us. Give it to our child.
|
||||
mCurrentMenu->ShortcutNavigation(aKeyEvent, aHandledFlag);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// This applies to us. Let's see if one of the shortcuts applies
|
||||
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);
|
||||
if (weakFrame.IsAlive()) {
|
||||
SetCurrentMenuItem(result);
|
||||
}
|
||||
if (weakResult.IsAlive()) {
|
||||
result->OpenMenu(PR_TRUE);
|
||||
if (weakResult.IsAlive()) {
|
||||
result->SelectFirstItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
||||
{
|
||||
nsNavigationDirection theDirection;
|
||||
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);
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
|
||||
aHandledFlag = PR_FALSE;
|
||||
|
||||
if (isOpen) {
|
||||
// Let the child menu try to handle it.
|
||||
mCurrentMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
|
||||
}
|
||||
|
||||
if (aHandledFlag)
|
||||
return NS_OK;
|
||||
|
||||
if NS_DIRECTION_IS_INLINE(theDirection) {
|
||||
|
||||
nsIMenuFrame* nextItem = (theDirection == eNavigationDirection_End) ?
|
||||
GetNextMenuItem(mCurrentMenu) :
|
||||
GetPreviousMenuItem(mCurrentMenu);
|
||||
|
||||
nsIFrame* nextFrame = nsnull;
|
||||
if (nextItem) {
|
||||
CallQueryInterface(nextItem, &nextFrame);
|
||||
}
|
||||
nsWeakFrame weakNext(nextFrame);
|
||||
SetCurrentMenuItem(nextItem);
|
||||
if (weakNext.IsAlive()) {
|
||||
PRBool nextIsOpen;
|
||||
nextItem->MenuIsOpen(nextIsOpen);
|
||||
if (nextIsOpen) {
|
||||
// Select the first item.
|
||||
nextItem->SelectFirstItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if NS_DIRECTION_IS_BLOCK(theDirection) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(PresContext()->PresShell(), this, nsnull, &immediateParent);
|
||||
if (!immediateParent)
|
||||
immediateParent = this;
|
||||
|
||||
nsIFrame* currFrame = nsnull;
|
||||
nsIFrame* startFrame = nsnull;
|
||||
if (aStart) {
|
||||
aStart->QueryInterface(NS_GET_IID(nsIFrame), (void**)&currFrame);
|
||||
if (currFrame) {
|
||||
startFrame = currFrame;
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
}
|
||||
else
|
||||
currFrame = immediateParent->GetFirstChild(nsnull);
|
||||
|
||||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
currFrame = immediateParent->GetFirstChild(nsnull);
|
||||
|
||||
// Still don't have anything. Try cycling from the beginning.
|
||||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
return aStart;
|
||||
}
|
||||
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(PresContext()->PresShell(), this, nsnull, &immediateParent);
|
||||
if (!immediateParent)
|
||||
immediateParent = this;
|
||||
|
||||
nsFrameList frames(immediateParent->GetFirstChild(nsnull));
|
||||
|
||||
nsIFrame* currFrame = nsnull;
|
||||
nsIFrame* startFrame = nsnull;
|
||||
if (aStart) {
|
||||
aStart->QueryInterface(NS_GET_IID(nsIFrame), (void**)&currFrame);
|
||||
if (currFrame) {
|
||||
startFrame = currFrame;
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
}
|
||||
else currFrame = frames.LastChild();
|
||||
|
||||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
||||
currFrame = frames.LastChild();
|
||||
|
||||
// Still don't have anything. Try cycling from the end.
|
||||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
return aStart;
|
||||
}
|
||||
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetCurrentMenuItem()
|
||||
{
|
||||
return mCurrentMenu;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::SetCurrentMenuItem(nsMenuFrame* aMenuItem)
|
||||
|
||||
NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
||||
{
|
||||
if (mCurrentMenu == aMenuItem)
|
||||
return NS_OK;
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
if (mCurrentMenu)
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
PRBool wasOpen = PR_FALSE;
|
||||
|
||||
// check if there's an open context menu, we ignore this
|
||||
if (nsMenuFrame::GetContextMenu())
|
||||
return NS_OK;
|
||||
|
||||
if (aMenuItem)
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
// Unset the current child.
|
||||
if (mCurrentMenu) {
|
||||
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);
|
||||
if (wasOpen&&!isDisabled)
|
||||
aMenuItem->OpenMenu(PR_TRUE);
|
||||
ClearRecentlyRolledUp();
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
|
||||
mCurrentMenu = aMenuItem;
|
||||
|
@ -332,103 +599,211 @@ nsMenuBarFrame::SetCurrentMenuItem(nsMenuFrame* aMenuItem)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarFrame::CurrentMenuIsBeingDestroyed()
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::Escape(PRBool& aHandledFlag)
|
||||
{
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
mCurrentMenu = nsnull;
|
||||
if (!mCurrentMenu)
|
||||
return NS_OK;
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
// See if our menu is open.
|
||||
PRBool isOpen = PR_FALSE;
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
if (isOpen) {
|
||||
// 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);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear our current menu item if we've got one.
|
||||
SetCurrentMenuItem(nsnull);
|
||||
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
|
||||
|
||||
SetActive(PR_FALSE);
|
||||
|
||||
// Clear out our dismissal listener
|
||||
nsMenuDismissalListener::Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::Enter()
|
||||
{
|
||||
if (!mCurrentMenu)
|
||||
return NS_OK;
|
||||
|
||||
ClearRecentlyRolledUp();
|
||||
|
||||
// See if our menu is open.
|
||||
PRBool isOpen = PR_FALSE;
|
||||
mCurrentMenu->MenuIsOpen(isOpen);
|
||||
if (isOpen) {
|
||||
// Let the child menu handle this.
|
||||
mCurrentMenu->Enter();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// It's us. Open the current menu.
|
||||
mCurrentMenu->OpenMenu(PR_TRUE);
|
||||
mCurrentMenu->SelectFirstItem();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
PRBool aSelectFirstItem)
|
||||
nsMenuBarFrame::ClearRecentlyRolledUp()
|
||||
{
|
||||
if (mCurrentMenu == aMenuItem)
|
||||
return NS_OK;
|
||||
// We're no longer in danger of popping down a menu from the same
|
||||
// click on the menubar, which was supposed to toggle the menu closed
|
||||
mRecentRollupMenu = nsnull;
|
||||
|
||||
// check if there's an open context menu, we ignore this
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && pm->HasContextMenu(nsnull))
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Unset the current child.
|
||||
PRBool wasOpen = PR_FALSE;
|
||||
if (mCurrentMenu) {
|
||||
wasOpen = mCurrentMenu->IsOpen();
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
if (wasOpen) {
|
||||
nsMenuPopupFrame* popupFrame = mCurrentMenu->GetPopup();
|
||||
if (popupFrame)
|
||||
pm->HidePopup(popupFrame->GetContent(), PR_FALSE, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::RecentlyRolledUp(nsIMenuFrame *aMenuFrame, PRBool *aJustRolledUp)
|
||||
{
|
||||
// Don't let a click reopen a menu that was just rolled up
|
||||
// from the same click. Otherwise, the user can't click on
|
||||
// a menubar item to toggle its submenu closed.
|
||||
*aJustRolledUp = (mRecentRollupMenu == aMenuFrame);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::HideChain()
|
||||
{
|
||||
// XXX hack if a context menu is active, do an Escape, which is
|
||||
// currently bugged and destroys everything. We need to close
|
||||
// the context menu first, otherwise SetCurrentMenuItem above
|
||||
// would get blocked.
|
||||
if (nsMenuFrame::GetContextMenu()) {
|
||||
PRBool dummy;
|
||||
mCurrentMenu->Escape(dummy);
|
||||
}
|
||||
|
||||
// set to null first in case the IsAlive check below returns false
|
||||
mCurrentMenu = nsnull;
|
||||
// Stop capturing rollups
|
||||
// (must do this during Hide, which happens before the menu item is executed,
|
||||
// since this reinstates normal event handling.)
|
||||
nsMenuDismissalListener::Shutdown();
|
||||
|
||||
// Set the new child.
|
||||
if (aMenuItem) {
|
||||
nsCOMPtr<nsIContent> content = aMenuItem->GetContent();
|
||||
nsWeakFrame weakNewMenu(aMenuItem);
|
||||
aMenuItem->SelectMenu(PR_TRUE);
|
||||
NS_ENSURE_TRUE(weakNewMenu.IsAlive(), NS_OK);
|
||||
mCurrentMenu = aMenuItem;
|
||||
if (wasOpen && !aMenuItem->IsDisabled())
|
||||
pm->ShowMenu(content, aSelectFirstItem, PR_TRUE);
|
||||
ClearRecentlyRolledUp();
|
||||
if (mCurrentMenu) {
|
||||
mCurrentMenu->ActivateMenu(PR_FALSE);
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
mRecentRollupMenu = mCurrentMenu;
|
||||
}
|
||||
|
||||
if (mIsActive) {
|
||||
ToggleMenuActiveState();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMenuFrame*
|
||||
nsMenuBarFrame::Enter()
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::DismissChain()
|
||||
{
|
||||
if (!mCurrentMenu)
|
||||
return nsnull;
|
||||
|
||||
if (mCurrentMenu->IsOpen())
|
||||
return mCurrentMenu->Enter();
|
||||
|
||||
return mCurrentMenu;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMenuBarFrame::MenuClosed()
|
||||
{
|
||||
SetActive(PR_FALSE);
|
||||
if (!mIsActive && mCurrentMenu) {
|
||||
mCurrentMenu->SelectMenu(PR_FALSE);
|
||||
mCurrentMenu = nsnull;
|
||||
return PR_TRUE;
|
||||
// Stop capturing rollups
|
||||
nsMenuDismissalListener::Shutdown();
|
||||
nsWeakFrame weakFrame(this);
|
||||
SetCurrentMenuItem(nsnull);
|
||||
if (weakFrame.IsAlive()) {
|
||||
SetActive(PR_FALSE);
|
||||
}
|
||||
return PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::KillPendingTimers ( )
|
||||
{
|
||||
return NS_OK;
|
||||
|
||||
} // KillPendingTimers
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::GetWidget(nsIWidget **aWidget)
|
||||
{
|
||||
// (pinkerton/hyatt)
|
||||
// since the menubar is a menuparent but not a menuItem, the win32 rollup code
|
||||
// would erroneously add the entire top-level window to the widget list built up for
|
||||
// determining if a click is in a submenu's menu chain. To get around this, we just
|
||||
// don't let the menubar have a widget. Things seem to work because the dismissal
|
||||
// listener is registered when a new menu is popped up, which is the only real reason
|
||||
// why we need a widget at all.
|
||||
*aWidget = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::InstallKeyboardNavigator()
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->SetActiveMenuBar(this, PR_TRUE);
|
||||
if (mKeyboardNavigator)
|
||||
return NS_OK;
|
||||
|
||||
mKeyboardNavigator = new nsMenuListener(this);
|
||||
NS_IF_ADDREF(mKeyboardNavigator);
|
||||
|
||||
mTarget->AddEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
mTarget->AddEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
mTarget->AddEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
|
||||
nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::RemoveKeyboardNavigator()
|
||||
{
|
||||
if (!mIsActive) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->SetActiveMenuBar(this, PR_FALSE);
|
||||
}
|
||||
if (!mKeyboardNavigator || mIsActive)
|
||||
return NS_OK;
|
||||
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
|
||||
|
||||
NS_IF_RELEASE(mKeyboardNavigator);
|
||||
|
||||
nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// helpers ///////////////////////////////////////////////////////////
|
||||
|
||||
PRBool
|
||||
nsMenuBarFrame::IsValidItem(nsIContent* aContent)
|
||||
{
|
||||
nsIAtom *tag = aContent->Tag();
|
||||
|
||||
return ((tag == nsGkAtoms::menu ||
|
||||
tag == nsGkAtoms::menuitem) &&
|
||||
!IsDisabled(aContent));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMenuBarFrame::IsDisabled(nsIContent* aContent)
|
||||
{
|
||||
return aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarFrame::Destroy()
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->SetActiveMenuBar(this, PR_FALSE);
|
||||
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE);
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE);
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE);
|
||||
|
@ -440,3 +815,4 @@ nsMenuBarFrame::Destroy()
|
|||
|
||||
nsBoxFrame::Destroy();
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIMenuFrame.h"
|
||||
#include "nsIPopupBoxObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#ifdef MOZ_XUL
|
||||
|
@ -58,7 +59,6 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsIRootBox.h"
|
||||
|
||||
nsXULTooltipListener* nsXULTooltipListener::mInstance = nsnull;
|
||||
|
@ -209,8 +209,8 @@ nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
|
|||
// mouse has really moved before proceeding.
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
|
||||
PRInt32 newMouseX, newMouseY;
|
||||
mouseEvent->GetScreenX(&newMouseX);
|
||||
mouseEvent->GetScreenY(&newMouseY);
|
||||
mouseEvent->GetClientX(&newMouseX);
|
||||
mouseEvent->GetClientY(&newMouseY);
|
||||
if (mMouseClientX == newMouseX && mMouseClientY == newMouseY)
|
||||
return NS_OK;
|
||||
mMouseClientX = newMouseX;
|
||||
|
@ -413,8 +413,12 @@ nsXULTooltipListener::ShowTooltip()
|
|||
// at this point, |mCurrentTooltip| holds the content node of
|
||||
// the tooltip. If there is an attribute on the popup telling us
|
||||
// not to create the auto-hide timer, don't.
|
||||
if (mCurrentTooltip->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
|
||||
nsGkAtoms::_true, eCaseMatters))
|
||||
nsCOMPtr<nsIDOMElement> tooltipEl(do_QueryInterface(mCurrentTooltip));
|
||||
if (!tooltipEl)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsAutoString noAutoHide;
|
||||
tooltipEl->GetAttribute(NS_LITERAL_STRING("noautohide"), noAutoHide);
|
||||
if (!noAutoHide.EqualsLiteral("true"))
|
||||
CreateAutoHideTimer();
|
||||
|
||||
// listen for popuphidden on the tooltip node, so that we can
|
||||
|
@ -485,38 +489,66 @@ nsXULTooltipListener::LaunchTooltip()
|
|||
if (!mCurrentTooltip)
|
||||
return;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsSourceTree && mNeedTitletip) {
|
||||
nsCOMPtr<nsITreeBoxObject> obx;
|
||||
GetSourceTreeBoxObject(getter_AddRefs(obx));
|
||||
nsCOMPtr<nsIBoxObject> popupBox;
|
||||
nsCOMPtr<nsIDOMXULElement> xulTooltipEl(do_QueryInterface(mCurrentTooltip));
|
||||
if (!xulTooltipEl) {
|
||||
NS_ERROR("tooltip isn't a XUL element!");
|
||||
return;
|
||||
}
|
||||
|
||||
SetTitletipLabel(obx, mCurrentTooltip, mLastTreeRow, mLastTreeCol);
|
||||
xulTooltipEl->GetBoxObject(getter_AddRefs(popupBox));
|
||||
nsCOMPtr<nsIPopupBoxObject> popupBoxObject(do_QueryInterface(popupBox));
|
||||
if (popupBoxObject) {
|
||||
PRInt32 x = mMouseClientX;
|
||||
PRInt32 y = mMouseClientY;
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsSourceTree && mNeedTitletip) {
|
||||
nsCOMPtr<nsITreeBoxObject> obx;
|
||||
GetSourceTreeBoxObject(getter_AddRefs(obx));
|
||||
#ifdef DEBUG_crap
|
||||
GetTreeCellCoords(obx, mSourceNode,
|
||||
mLastTreeRow, mLastTreeCol, &x, &y);
|
||||
#endif
|
||||
|
||||
SetTitletipLabel(obx, mCurrentTooltip, mLastTreeRow, mLastTreeCol);
|
||||
if (!mCurrentTooltip) {
|
||||
// Because of mutation events, mCurrentTooltip can be null.
|
||||
return;
|
||||
}
|
||||
mCurrentTooltip->SetAttr(kNameSpaceID_None, nsGkAtoms::titletip,
|
||||
NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
} else {
|
||||
mCurrentTooltip->UnsetAttr(kNameSpaceID_None, nsGkAtoms::titletip,
|
||||
PR_TRUE);
|
||||
}
|
||||
if (!mCurrentTooltip) {
|
||||
// Because of mutation events, mCurrentTooltip can be null.
|
||||
return;
|
||||
}
|
||||
mCurrentTooltip->SetAttr(nsnull, nsGkAtoms::titletip, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
} else {
|
||||
mCurrentTooltip->UnsetAttr(nsnull, nsGkAtoms::titletip, PR_TRUE);
|
||||
}
|
||||
if (!mCurrentTooltip) {
|
||||
// Because of mutation events, mCurrentTooltip can be null.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->ShowPopupAtScreen(mCurrentTooltip, mMouseClientX, mMouseClientY, PR_FALSE);
|
||||
nsCOMPtr<nsIDOMElement> targetEl(do_QueryInterface(mSourceNode));
|
||||
popupBoxObject->ShowPopup(targetEl, xulTooltipEl, x, y,
|
||||
NS_LITERAL_STRING("tooltip").get(),
|
||||
NS_LITERAL_STRING("none").get(),
|
||||
NS_LITERAL_STRING("topleft").get());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTooltipListener::HideTooltip()
|
||||
{
|
||||
if (mCurrentTooltip) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->HidePopup(mCurrentTooltip, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
// hide the popup through its box object
|
||||
nsCOMPtr<nsIDOMXULElement> tooltipEl(do_QueryInterface(mCurrentTooltip));
|
||||
nsCOMPtr<nsIBoxObject> boxObject;
|
||||
if (tooltipEl)
|
||||
tooltipEl->GetBoxObject(getter_AddRefs(boxObject));
|
||||
nsCOMPtr<nsIPopupBoxObject> popupObject(do_QueryInterface(boxObject));
|
||||
if (popupObject)
|
||||
popupObject->HidePopup();
|
||||
}
|
||||
|
||||
DestroyTooltip();
|
||||
|
@ -637,9 +669,10 @@ nsXULTooltipListener::GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip)
|
|||
nsIDocument* doc = parent->GetCurrentDoc();
|
||||
nsIPresShell* presShell = doc ? doc->GetPrimaryShell() : nsnull;
|
||||
nsIFrame* frame = presShell ? presShell->GetPrimaryFrameFor(parent) : nsnull;
|
||||
if (frame && frame->GetType() == nsGkAtoms::menuFrame) {
|
||||
NS_WARNING("Menu cannot be used as a tooltip");
|
||||
return NS_ERROR_FAILURE;
|
||||
if (frame) {
|
||||
nsIMenuFrame* menu = nsnull;
|
||||
CallQueryInterface(frame, &menu);
|
||||
NS_ENSURE_FALSE(menu, NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -708,7 +741,7 @@ nsXULTooltipListener::CreateAutoHideTimer()
|
|||
mAutoHideTimer->Cancel();
|
||||
mAutoHideTimer = nsnull;
|
||||
}
|
||||
|
||||
|
||||
mAutoHideTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if ( mAutoHideTimer )
|
||||
mAutoHideTimer->InitWithFuncCallback(sAutoHideCallback, this, kTooltipAutoHideTime,
|
||||
|
|
Загрузка…
Ссылка в новой задаче