diff --git a/mozilla/layout/xul/base/src/nsMenuBarFrame.cpp b/mozilla/layout/xul/base/src/nsMenuBarFrame.cpp index df5560bf17c..f52c7bb25b6 100644 --- a/mozilla/layout/xul/base/src/nsMenuBarFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuBarFrame.cpp @@ -571,6 +571,17 @@ nsMenuBarFrame::DismissChain() 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; + +#if DONT_WANT_TO_DO_THIS // Get parent view nsIView * view = nsnull; nsMenuPopupFrame::GetNearestEnclosingView(mPresContext, this, &view); @@ -578,7 +589,7 @@ nsMenuBarFrame::GetWidget(nsIWidget **aWidget) return NS_OK; view->GetWidget(*aWidget); - return NS_OK; +#endif } NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsMenuDismissalListener.cpp b/mozilla/layout/xul/base/src/nsMenuDismissalListener.cpp index 887590d08f6..5c036dd26cb 100644 --- a/mozilla/layout/xul/base/src/nsMenuDismissalListener.cpp +++ b/mozilla/layout/xul/base/src/nsMenuDismissalListener.cpp @@ -32,7 +32,7 @@ NS_IMPL_ADDREF(nsMenuDismissalListener) NS_IMPL_RELEASE(nsMenuDismissalListener) -NS_IMPL_QUERY_INTERFACE2(nsMenuDismissalListener, nsIDOMMouseListener, nsIRollupListener) +NS_IMPL_QUERY_INTERFACE3(nsMenuDismissalListener, nsIDOMMouseListener, nsIMenuRollup, nsIRollupListener) //////////////////////////////////////////////////////////////////////// @@ -75,7 +75,7 @@ nsMenuDismissalListener::SetCurrentMenuParent(nsIMenuParent* aMenuParent) if (!widget) return; - widget->CaptureRollupEvents(this, PR_TRUE, PR_FALSE); + widget->CaptureRollupEvents(this, PR_TRUE, PR_TRUE); mWidget = widget; NS_ADDREF(nsMenuFrame::mDismissalListener = this); @@ -97,6 +97,68 @@ nsMenuDismissalListener::Rollup() return NS_OK; } + +// uggggh. +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); + + +NS_IMETHODIMP +nsMenuDismissalListener::GetSubmenuWidgetChain(nsISupportsArray **_retval) +{ + NS_NewISupportsArray ( _retval ); + nsCOMPtr curr ( dont_QueryInterface(mMenuParent) ); + while ( curr ) { + nsCOMPtr widget; + curr->GetWidget ( getter_AddRefs(widget) ); + nsCOMPtr genericWidget ( do_QueryInterface(widget) ); + (**_retval).AppendElement ( genericWidget ); + + // move up the chain + nsIFrame* currAsFrame = nsnull; + if ( NS_SUCCEEDED(curr->QueryInterface(kIFrameIID, NS_REINTERPRET_CAST(void**,&currAsFrame))) ) { + nsIFrame* parentFrame = nsnull; + currAsFrame->GetParent(&parentFrame); + nsIMenuParent* next; + nsCOMPtr menuFrame ( do_QueryInterface(parentFrame) ); + if ( menuFrame ) { + menuFrame->GetMenuParent ( &next ); // Advance to next parent + curr = dont_AddRef(next); + } + else { + // we are a menuParent but not a menuFrame. This is probably the case + // of the menu bar. Nothing to do here, really. + return NS_OK; + } + } + else { + // We've run into a menu parent that isn't a frame at all. Not good. + NS_WARNING ( "nsIMenuParent that is not a nsIFrame" ); + return NS_ERROR_FAILURE; + } + } // foreach parent menu + + return NS_OK; +} + +#if 0 +NS_IMETHODIMP +nsMenuDismissalListener::FirstMenuParent(nsIMenuParent * *_retval) +{ + NS_IF_ADDREF(*_retval = mMenuParent); + + return NS_OK; +} + + +NS_IMETHODIMP +nsMenuDismissalListener::NextMenuParent(nsIMenuParent * inCurrent, nsIMenuParent * *_retval) +{ +//XXX for now don't return anything in the chain + *_retval = nsnull; + return NS_OK; +} +#endif + NS_IMETHODIMP nsMenuDismissalListener::Unregister() { diff --git a/mozilla/layout/xul/base/src/nsMenuDismissalListener.h b/mozilla/layout/xul/base/src/nsMenuDismissalListener.h index a28b75cf42a..b7984905e03 100644 --- a/mozilla/layout/xul/base/src/nsMenuDismissalListener.h +++ b/mozilla/layout/xul/base/src/nsMenuDismissalListener.h @@ -27,6 +27,7 @@ #include "nsIWidget.h" #include "nsIDOMMouseListener.h" #include "nsIRollupListener.h" +#include "nsIMenuRollup.h" #include "nsIDOMEventReceiver.h" class nsMenuPopupFrame; @@ -35,7 +36,7 @@ class nsIMenuParent; /** editor Implementation of the DragListener interface */ -class nsMenuDismissalListener : public nsIDOMMouseListener, public nsIRollupListener +class nsMenuDismissalListener : public nsIDOMMouseListener, public nsIMenuRollup, public nsIRollupListener { public: /** default constructor @@ -55,8 +56,9 @@ public: virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }; virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }; - NS_IMETHOD Rollup(); NS_DECL_ISUPPORTS + NS_DECL_NSIROLLUPLISTENER + NS_DECL_NSIMENUROLLUP NS_IMETHOD EnableListener(PRBool aEnabled); void SetCurrentMenuParent(nsIMenuParent* aMenuParent); diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index fdc40eae3ce..4da2c985854 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -265,24 +265,25 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext, OpenMenu(PR_TRUE); } } - else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN && !IsDisabled()) { + else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN && !IsDisabled() && IsMenu() ) { PRBool isMenuBar = PR_FALSE; if (mMenuParent) mMenuParent->IsMenuBar(isMenuBar); // The menu item was selected. Bring up the menu. // We have children. - if (mIsMenu) + if ( isMenuBar || !mMenuParent ) { ToggleMenuState(); - if (isMenuBar && mIsMenu) { - - if (!IsOpen()) { + if (!IsOpen() && mMenuParent) { // We closed up. The menu bar should always be // deactivated when this happens. mMenuParent->SetActive(PR_FALSE); } } + else + if ( !IsOpen() ) + OpenMenu(PR_TRUE); } else if ( aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP && mMenuParent && !IsDisabled()) { // if this menu is a context menu it accepts right-clicks...fire away!