2001-09-28 20:14:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
1999-08-06 18:16:27 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/NPL/
|
1999-08-06 18:16:27 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
1999-08-06 18:16:27 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2000-03-21 13:24:48 +00:00
|
|
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
2000-02-02 22:24:56 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2000-03-01 03:12:51 +00:00
|
|
|
* Dean Tessman <dean_tessman@hotmail.com>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1999-08-06 18:16:27 +00:00
|
|
|
|
|
|
|
#include "nsXULAtoms.h"
|
|
|
|
#include "nsHTMLAtoms.h"
|
|
|
|
#include "nsPopupSetFrame.h"
|
1999-09-25 03:39:35 +00:00
|
|
|
#include "nsIMenuParent.h"
|
|
|
|
#include "nsMenuFrame.h"
|
1999-08-06 18:16:27 +00:00
|
|
|
#include "nsBoxFrame.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "prtypes.h"
|
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsIStyleContext.h"
|
|
|
|
#include "nsCSSRendering.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsLayoutAtoms.h"
|
|
|
|
#include "nsMenuPopupFrame.h"
|
|
|
|
#include "nsMenuBarFrame.h"
|
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIWidget.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIDOMNSDocument.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
#include "nsIDOMXULDocument.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
#include "nsISupportsArray.h"
|
|
|
|
#include "nsIDOMText.h"
|
2000-03-31 07:02:06 +00:00
|
|
|
#include "nsBoxLayoutState.h"
|
2000-05-15 04:12:31 +00:00
|
|
|
#include "nsIScrollableFrame.h"
|
2000-08-03 00:22:36 +00:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
2001-07-16 02:40:48 +00:00
|
|
|
#include "nsGUIEvent.h"
|
1999-08-06 18:16:27 +00:00
|
|
|
|
2000-07-28 22:09:45 +00:00
|
|
|
#define NS_MENU_POPUP_LIST_INDEX 0
|
1999-08-06 18:16:27 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupFrameList::nsPopupFrameList(nsIContent* aPopupContent, nsPopupFrameList* aNext)
|
|
|
|
:mNextPopup(aNext),
|
|
|
|
mPopupFrame(nsnull),
|
2001-10-25 03:21:53 +00:00
|
|
|
mPopupContent(aPopupContent),
|
|
|
|
mElementContent(nsnull),
|
2001-08-18 01:04:47 +00:00
|
|
|
mCreateHandlerSucceeded(PR_FALSE),
|
|
|
|
mLastPref(-1,-1)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPopupFrameList* nsPopupFrameList::GetEntry(nsIContent* aPopupContent) {
|
|
|
|
if (aPopupContent == mPopupContent)
|
|
|
|
return this;
|
|
|
|
|
|
|
|
if (mNextPopup)
|
|
|
|
return mNextPopup->GetEntry(aPopupContent);
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPopupFrameList* nsPopupFrameList::GetEntryByFrame(nsIFrame* aPopupFrame) {
|
|
|
|
if (aPopupFrame == mPopupFrame)
|
|
|
|
return this;
|
|
|
|
|
|
|
|
if (mNextPopup)
|
|
|
|
return mNextPopup->GetEntryByFrame(aPopupFrame);
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
2000-08-17 09:15:51 +00:00
|
|
|
|
1999-08-06 18:16:27 +00:00
|
|
|
//
|
|
|
|
// NS_NewPopupSetFrame
|
|
|
|
//
|
|
|
|
// Wrapper for creating a new menu popup container
|
|
|
|
//
|
|
|
|
nsresult
|
1999-12-04 23:49:50 +00:00
|
|
|
NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
1999-08-06 18:16:27 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
|
|
if (nsnull == aNewFrame) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2000-03-02 03:01:30 +00:00
|
|
|
nsPopupSetFrame* it = new (aPresShell) nsPopupSetFrame (aPresShell);
|
1999-08-06 18:16:27 +00:00
|
|
|
if ( !it )
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
*aNewFrame = it;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
nsPopupSetFrame::AddRef(void)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
nsPopupSetFrame::Release(void)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-12-22 01:57:29 +00:00
|
|
|
//
|
|
|
|
// QueryInterface
|
|
|
|
//
|
1999-12-21 19:28:15 +00:00
|
|
|
NS_INTERFACE_MAP_BEGIN(nsPopupSetFrame)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIPopupSetFrame)
|
2000-01-26 22:35:53 +00:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
1999-12-22 01:57:29 +00:00
|
|
|
|
1999-08-06 18:16:27 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// nsPopupSetFrame cntr
|
|
|
|
//
|
2000-03-02 03:01:30 +00:00
|
|
|
nsPopupSetFrame::nsPopupSetFrame(nsIPresShell* aShell):nsBoxFrame(aShell),
|
2000-05-15 04:12:31 +00:00
|
|
|
mPresContext(nsnull),
|
2000-08-03 00:22:36 +00:00
|
|
|
mFrameConstructor(nsnull)
|
1999-08-06 18:16:27 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
} // cntr
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsPopupSetFrame::Init(nsIPresContext* aPresContext,
|
1999-08-06 18:16:27 +00:00
|
|
|
nsIContent* aContent,
|
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIStyleContext* aContext,
|
|
|
|
nsIFrame* aPrevInFlow)
|
|
|
|
{
|
1999-11-24 06:03:41 +00:00
|
|
|
mPresContext = aPresContext; // Don't addref it. Our lifetime is shorter.
|
1999-08-06 18:16:27 +00:00
|
|
|
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsPopupSetFrame::Destroy(nsIPresContext* aPresContext)
|
1999-08-06 18:16:27 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
// Remove our frame list.
|
2000-08-03 00:22:36 +00:00
|
|
|
if (mFrameConstructor) {
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupFrameList* curFrame = mPopupList;
|
2000-08-03 00:22:36 +00:00
|
|
|
while (curFrame) {
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupFrameList* temp = curFrame;
|
2001-08-18 02:03:37 +00:00
|
|
|
if (curFrame->mPopupFrame)
|
|
|
|
curFrame->mPopupFrame->Destroy(aPresContext);
|
2001-08-18 01:04:47 +00:00
|
|
|
curFrame = curFrame->mNextPopup;
|
|
|
|
temp->mNextPopup = nsnull;
|
|
|
|
delete temp;
|
2000-08-03 00:22:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-06 18:16:27 +00:00
|
|
|
return nsBoxFrame::Destroy(aPresContext);
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
NS_IMETHODIMP
|
2000-07-07 22:24:06 +00:00
|
|
|
nsPopupSetFrame::DoLayout(nsBoxLayoutState& aState)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
// lay us out
|
2000-07-07 22:24:06 +00:00
|
|
|
nsresult rv = nsBoxFrame::DoLayout(aState);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// lay out all of our currently open popups.
|
|
|
|
nsPopupFrameList* currEntry = mPopupList;
|
|
|
|
while (currEntry) {
|
|
|
|
nsIFrame* popupChild = currEntry->mPopupFrame;
|
|
|
|
if (popupChild) {
|
|
|
|
nsIBox* ibox = nsnull;
|
|
|
|
nsresult rv2 = popupChild->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv2) && ibox,"popupChild is not box!!");
|
|
|
|
|
|
|
|
// then get its preferred size
|
|
|
|
nsSize prefSize(0,0);
|
|
|
|
nsSize minSize(0,0);
|
|
|
|
nsSize maxSize(0,0);
|
|
|
|
|
|
|
|
ibox->GetPrefSize(aState, prefSize);
|
|
|
|
ibox->GetMinSize(aState, minSize);
|
|
|
|
ibox->GetMaxSize(aState, maxSize);
|
|
|
|
|
|
|
|
BoundsCheck(minSize, prefSize, maxSize);
|
|
|
|
|
|
|
|
// if the pref size changed then set bounds to be the pref size
|
|
|
|
// and sync the view. Also set new pref size.
|
|
|
|
// if (currEntry->mLastPref != prefSize) {
|
|
|
|
ibox->SetBounds(aState, nsRect(0,0,prefSize.width, prefSize.height));
|
|
|
|
RepositionPopup(currEntry, aState);
|
|
|
|
currEntry->mLastPref = prefSize;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// is the new size too small? Make sure we handle scrollbars correctly
|
|
|
|
nsIBox* child;
|
|
|
|
ibox->GetChildBox(&child);
|
|
|
|
|
|
|
|
nsRect bounds(0,0,0,0);
|
|
|
|
ibox->GetBounds(bounds);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIScrollableFrame> scrollframe = do_QueryInterface(child);
|
|
|
|
if (scrollframe) {
|
|
|
|
nsIScrollableFrame::nsScrollPref pref;
|
|
|
|
scrollframe->GetScrollPreference(aState.GetPresContext(), &pref);
|
|
|
|
|
|
|
|
if (pref == nsIScrollableFrame::Auto)
|
|
|
|
{
|
|
|
|
// if our pref height
|
|
|
|
if (bounds.height < prefSize.height) {
|
|
|
|
// layout the child
|
|
|
|
ibox->Layout(aState);
|
|
|
|
|
|
|
|
nscoord width;
|
|
|
|
nscoord height;
|
|
|
|
scrollframe->GetScrollbarSizes(aState.GetPresContext(), &width, &height);
|
|
|
|
if (bounds.width < prefSize.width + width)
|
|
|
|
{
|
|
|
|
bounds.width += width;
|
|
|
|
//printf("Width=%d\n",width);
|
|
|
|
ibox->SetBounds(aState, bounds);
|
|
|
|
}
|
|
|
|
}
|
2000-05-15 04:12:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// layout the child
|
|
|
|
ibox->Layout(aState);
|
|
|
|
|
|
|
|
// only size popup if open
|
|
|
|
if (currEntry->mCreateHandlerSucceeded) {
|
|
|
|
nsIView* view = nsnull;
|
|
|
|
popupChild->GetView(aState.GetPresContext(), &view);
|
|
|
|
nsCOMPtr<nsIViewManager> viewManager;
|
|
|
|
view->GetViewManager(*getter_AddRefs(viewManager));
|
2001-12-01 14:31:45 +00:00
|
|
|
nsRect r(0, 0, bounds.width, bounds.height);
|
|
|
|
viewManager->ResizeView(view, r);
|
2001-08-18 01:04:47 +00:00
|
|
|
viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
|
|
|
|
}
|
2000-05-15 04:12:31 +00:00
|
|
|
}
|
2001-08-18 01:04:47 +00:00
|
|
|
|
|
|
|
currEntry = currEntry->mNextPopup;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SyncLayout(aState);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-08-06 18:16:27 +00:00
|
|
|
|
2000-03-02 03:01:30 +00:00
|
|
|
NS_IMETHODIMP
|
2000-03-31 07:02:06 +00:00
|
|
|
nsPopupSetFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug)
|
2000-03-02 03:01:30 +00:00
|
|
|
{
|
|
|
|
// see if our state matches the given debug state
|
|
|
|
PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
|
|
|
|
PRBool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
|
|
|
|
|
|
|
|
// if it doesn't then tell each child below us the new debug state
|
|
|
|
if (debugChanged)
|
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
// XXXdwh fix later. nobody uses this anymore anyway.
|
2000-03-02 03:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2000-03-31 07:02:06 +00:00
|
|
|
nsPopupSetFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug)
|
2000-03-02 03:01:30 +00:00
|
|
|
{
|
|
|
|
if (!aList)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
while (aList) {
|
|
|
|
nsIBox* ibox = nsnull;
|
|
|
|
if (NS_SUCCEEDED(aList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) {
|
2000-03-31 07:02:06 +00:00
|
|
|
ibox->SetDebug(aState, aDebug);
|
2000-03-02 03:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
aList->GetNextSibling(&aList);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-08-06 18:16:27 +00:00
|
|
|
|
2000-04-05 23:46:48 +00:00
|
|
|
void
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::RepositionPopup(nsPopupFrameList* aEntry, nsBoxLayoutState& aState)
|
1999-08-06 18:16:27 +00:00
|
|
|
{
|
|
|
|
// Sync up the view.
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aEntry && aEntry->mElementContent) {
|
2000-06-29 22:30:27 +00:00
|
|
|
nsIFrame* frameToSyncTo = nsnull;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
2000-04-05 23:46:48 +00:00
|
|
|
nsIPresContext* presContext = aState.GetPresContext();
|
2000-06-29 22:30:27 +00:00
|
|
|
presContext->GetShell(getter_AddRefs(presShell));
|
2001-08-18 01:04:47 +00:00
|
|
|
presShell->GetPrimaryFrameFor(aEntry->mElementContent, &frameToSyncTo );
|
|
|
|
((nsMenuPopupFrame*)(aEntry->mPopupFrame))->SyncViewWithFrame(presContext,
|
|
|
|
aEntry->mPopupAnchor, aEntry->mPopupAlign, frameToSyncTo, aEntry->mXPos, aEntry->mYPos);
|
1999-08-06 18:16:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupContent,
|
|
|
|
PRInt32 aXPos, PRInt32 aYPos,
|
|
|
|
const nsString& aPopupType, const nsString& anAnchorAlignment,
|
|
|
|
const nsString& aPopupAlignment)
|
1999-08-06 18:16:27 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
// First fire the popupshowing event.
|
2001-12-04 22:32:49 +00:00
|
|
|
if (!OnCreate(aXPos, aYPos, aPopupContent))
|
1999-08-06 18:16:27 +00:00
|
|
|
return NS_OK;
|
2001-08-18 01:04:47 +00:00
|
|
|
|
|
|
|
// See if we already have an entry in our list. We must create a new one on a miss.
|
|
|
|
nsPopupFrameList* entry = nsnull;
|
|
|
|
if (mPopupList)
|
|
|
|
entry = mPopupList->GetEntry(aPopupContent);
|
|
|
|
if (!entry) {
|
|
|
|
entry = new nsPopupFrameList(aPopupContent, mPopupList);
|
|
|
|
mPopupList = entry;
|
1999-08-06 18:16:27 +00:00
|
|
|
}
|
1999-08-19 03:51:25 +00:00
|
|
|
|
2000-06-29 22:30:27 +00:00
|
|
|
// Cache the element content we're supposed to sync to
|
2001-08-18 01:04:47 +00:00
|
|
|
entry->mPopupType = aPopupType;
|
|
|
|
entry->mElementContent = aElementContent;
|
|
|
|
entry->mPopupAlign = aPopupAlignment;
|
|
|
|
entry->mPopupAnchor = anAnchorAlignment;
|
|
|
|
entry->mXPos = aXPos;
|
|
|
|
entry->mYPos = aYPos;
|
|
|
|
|
|
|
|
// If a frame exists already, go ahead and use it.
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
mPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
shell->GetPrimaryFrameFor(aPopupContent, &entry->mPopupFrame);
|
1999-09-10 08:47:12 +00:00
|
|
|
|
2000-05-11 00:52:34 +00:00
|
|
|
#ifdef DEBUG_PINK
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("X Pos: %d\n", mXPos);
|
|
|
|
printf("Y Pos: %d\n", mYPos);
|
2000-05-11 00:52:34 +00:00
|
|
|
#endif
|
2000-05-10 01:43:54 +00:00
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
// Generate the popup.
|
2001-08-18 01:04:47 +00:00
|
|
|
entry->mCreateHandlerSucceeded = PR_TRUE;
|
1999-09-10 08:47:12 +00:00
|
|
|
MarkAsGenerated(aPopupContent);
|
|
|
|
|
2000-03-01 03:12:51 +00:00
|
|
|
// determine if this menu is a context menu and flag it
|
2001-08-18 01:04:47 +00:00
|
|
|
nsIFrame* activeChild = entry->mPopupFrame;
|
2002-08-06 12:48:28 +00:00
|
|
|
nsIMenuParent* childPopup = nsnull;
|
|
|
|
if (activeChild)
|
|
|
|
CallQueryInterface(activeChild, &childPopup);
|
2000-08-30 02:40:19 +00:00
|
|
|
if ( childPopup && aPopupType == NS_LITERAL_STRING("context") )
|
2000-03-01 03:12:51 +00:00
|
|
|
childPopup->SetIsContextMenu(PR_TRUE);
|
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
// Now open the popup.
|
2001-08-18 01:04:47 +00:00
|
|
|
OpenPopup(entry, PR_TRUE);
|
1999-08-19 22:10:24 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// Now fire the popupshown event.
|
2001-12-04 22:32:49 +00:00
|
|
|
OnCreated(aXPos, aYPos, aPopupContent);
|
2001-08-06 21:49:35 +00:00
|
|
|
|
1999-08-19 22:10:24 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-09-09 01:07:06 +00:00
|
|
|
|
1999-09-21 01:03:00 +00:00
|
|
|
NS_IMETHODIMP
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::HidePopup(nsIFrame* aPopup)
|
1999-09-21 01:03:00 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
if (!mPopupList)
|
|
|
|
return NS_OK; // No active popups
|
|
|
|
|
|
|
|
nsPopupFrameList* entry = mPopupList->GetEntryByFrame(aPopup);
|
|
|
|
if (entry && entry->mCreateHandlerSucceeded)
|
|
|
|
ActivatePopup(entry, PR_FALSE);
|
1999-09-21 01:03:00 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::DestroyPopup(nsIFrame* aPopup)
|
1999-09-21 01:03:00 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
if (!mPopupList)
|
|
|
|
return NS_OK; // No active popups
|
|
|
|
|
|
|
|
nsPopupFrameList* entry = mPopupList->GetEntryByFrame(aPopup);
|
2000-05-12 02:58:21 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
if (entry && entry->mCreateHandlerSucceeded) { // ensure the popup was created before we try to destroy it
|
|
|
|
OpenPopup(entry, PR_FALSE);
|
|
|
|
entry->mPopupType.SetLength(0);
|
|
|
|
|
|
|
|
// clear things out for next time
|
|
|
|
entry->mCreateHandlerSucceeded = PR_FALSE;
|
|
|
|
entry->mElementContent = nsnull;
|
|
|
|
entry->mXPos = entry->mYPos = 0;
|
|
|
|
entry->mLastPref.width = -1;
|
|
|
|
entry->mLastPref.height = -1;
|
|
|
|
|
2001-09-22 00:32:23 +00:00
|
|
|
// ungenerate the popup.
|
2001-08-18 01:04:47 +00:00
|
|
|
entry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, PR_TRUE);
|
|
|
|
}
|
2000-05-12 02:58:21 +00:00
|
|
|
|
1999-09-21 01:03:00 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-09-09 01:07:06 +00:00
|
|
|
void
|
|
|
|
nsPopupSetFrame::MarkAsGenerated(nsIContent* aPopupContent)
|
|
|
|
{
|
|
|
|
// Set our attribute, but only if we aren't already generated.
|
|
|
|
// Retrieve the menugenerated attribute.
|
|
|
|
nsAutoString value;
|
2001-08-17 08:14:14 +00:00
|
|
|
aPopupContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated,
|
|
|
|
value);
|
2000-08-30 02:40:19 +00:00
|
|
|
if (value != NS_LITERAL_STRING("true")) {
|
1999-09-10 08:47:12 +00:00
|
|
|
// Generate this element.
|
2001-08-17 08:14:14 +00:00
|
|
|
aPopupContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, NS_LITERAL_STRING("true"),
|
|
|
|
PR_TRUE);
|
1999-09-09 01:07:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::OpenPopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
|
1999-09-09 01:07:06 +00:00
|
|
|
{
|
1999-09-10 08:47:12 +00:00
|
|
|
if (aActivateFlag) {
|
2001-08-18 01:04:47 +00:00
|
|
|
ActivatePopup(aEntry, PR_TRUE);
|
1999-09-25 03:39:35 +00:00
|
|
|
|
2000-05-10 01:43:54 +00:00
|
|
|
// register the rollup listeners, etc, but not if we're a tooltip
|
2001-08-18 01:04:47 +00:00
|
|
|
nsIFrame* activeChild = aEntry->mPopupFrame;
|
2002-08-06 12:48:28 +00:00
|
|
|
nsIMenuParent* childPopup = nsnull;
|
|
|
|
if (activeChild)
|
|
|
|
CallQueryInterface(activeChild, &childPopup);
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aEntry->mPopupType != NS_LITERAL_STRING("tooltip"))
|
2000-05-10 01:43:54 +00:00
|
|
|
UpdateDismissalListener(childPopup);
|
2000-05-01 22:27:16 +00:00
|
|
|
|
|
|
|
// First check and make sure this popup wants keyboard navigation
|
2000-05-10 01:43:54 +00:00
|
|
|
nsAutoString property;
|
2000-05-23 00:56:52 +00:00
|
|
|
// Tooltips don't get keyboard navigation
|
2001-08-18 01:04:47 +00:00
|
|
|
aEntry->mPopupContent->GetAttr(kNameSpaceID_None, nsXULAtoms::ignorekeys, property);
|
|
|
|
if (property != NS_LITERAL_STRING("true") &&
|
|
|
|
childPopup &&
|
|
|
|
aEntry->mPopupType != NS_LITERAL_STRING("tooltip"))
|
2000-05-04 18:50:34 +00:00
|
|
|
childPopup->InstallKeyboardNavigator();
|
2000-05-01 22:27:16 +00:00
|
|
|
}
|
1999-09-10 08:47:12 +00:00
|
|
|
else {
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aEntry->mCreateHandlerSucceeded && !OnDestroy(aEntry->mPopupContent))
|
1999-09-25 03:39:35 +00:00
|
|
|
return;
|
|
|
|
|
2000-05-10 01:43:54 +00:00
|
|
|
// Unregister, but not if we're a tooltip
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aEntry->mPopupType != NS_LITERAL_STRING("tooltip") ) {
|
2001-09-10 07:34:54 +00:00
|
|
|
if (nsMenuFrame::sDismissalListener)
|
|
|
|
nsMenuFrame::sDismissalListener->Unregister();
|
1999-09-25 03:39:35 +00:00
|
|
|
}
|
2000-05-10 01:43:54 +00:00
|
|
|
|
2000-02-09 09:34:35 +00:00
|
|
|
// Remove any keyboard navigators
|
2002-08-06 12:48:28 +00:00
|
|
|
nsIMenuParent* childPopup = nsnull;
|
|
|
|
if (aEntry->mPopupFrame)
|
|
|
|
CallQueryInterface(aEntry->mPopupFrame, &childPopup);
|
2001-08-18 01:04:47 +00:00
|
|
|
if (childPopup)
|
2000-05-04 18:50:34 +00:00
|
|
|
childPopup->RemoveKeyboardNavigator();
|
2000-02-09 09:34:35 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
ActivatePopup(aEntry, PR_FALSE);
|
2001-08-06 21:49:35 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
OnDestroyed(aEntry->mPopupContent);
|
1999-09-09 01:07:06 +00:00
|
|
|
}
|
2001-08-18 01:04:47 +00:00
|
|
|
|
|
|
|
nsBoxLayoutState state(mPresContext);
|
|
|
|
MarkDirtyChildren(state); // Mark ourselves dirty.
|
1999-09-09 01:07:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
|
1999-09-09 01:07:06 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aEntry->mPopupContent) {
|
2000-02-11 02:02:06 +00:00
|
|
|
// When we sync the popup view with the frame, we'll show the popup if |menutobedisplayed|
|
2000-05-15 04:12:31 +00:00
|
|
|
// is set by setting the |menuactive| attribute. This used to trip css into showing the menu
|
|
|
|
// but now we do it ourselves.
|
1999-09-10 08:47:12 +00:00
|
|
|
if (aActivateFlag)
|
2001-09-10 07:34:54 +00:00
|
|
|
// XXXben hook in |width| and |height| usage here?
|
2001-08-18 01:04:47 +00:00
|
|
|
aEntry->mPopupContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, NS_LITERAL_STRING("true"), PR_TRUE);
|
2000-02-11 02:02:06 +00:00
|
|
|
else {
|
2001-08-18 01:04:47 +00:00
|
|
|
aEntry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE);
|
|
|
|
aEntry->mPopupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE);
|
2000-05-15 04:12:31 +00:00
|
|
|
|
2001-04-11 23:02:49 +00:00
|
|
|
// get rid of the reflows we just created. If we leave them hanging around, we
|
|
|
|
// can get into trouble if a dialog with a modal event loop comes along and
|
|
|
|
// processes the reflows before we get to call DestroyChain(). Processing the
|
|
|
|
// reflow will cause the popup to show itself again. (bug 71219)
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
2001-08-18 01:04:47 +00:00
|
|
|
aEntry->mPopupContent->GetDocument(*getter_AddRefs(doc));
|
|
|
|
if (doc)
|
2001-07-16 22:15:29 +00:00
|
|
|
doc->FlushPendingNotifications();
|
2001-04-11 23:02:49 +00:00
|
|
|
|
2001-06-04 23:55:48 +00:00
|
|
|
// make sure we hide the popup. We can't assume that we'll have a view
|
|
|
|
// since we could be cleaning up after someone that didn't correctly
|
|
|
|
// destroy the popup.
|
2001-08-18 01:04:47 +00:00
|
|
|
nsIFrame* activeChild = aEntry->mPopupFrame;
|
2000-05-15 04:12:31 +00:00
|
|
|
nsIView* view = nsnull;
|
2001-08-18 01:04:47 +00:00
|
|
|
if (activeChild) {
|
2001-06-04 23:55:48 +00:00
|
|
|
activeChild->GetView(mPresContext, &view);
|
2001-08-18 01:04:47 +00:00
|
|
|
NS_ASSERTION(view, "View is gone, looks like someone forgot to roll up the popup!");
|
|
|
|
if (view) {
|
2001-06-04 23:55:48 +00:00
|
|
|
nsCOMPtr<nsIViewManager> viewManager;
|
|
|
|
view->GetViewManager(*getter_AddRefs(viewManager));
|
|
|
|
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
|
2001-12-01 14:31:45 +00:00
|
|
|
nsRect r(0, 0, 0, 0);
|
|
|
|
viewManager->ResizeView(view, r);
|
2001-06-04 23:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
2000-02-11 02:02:06 +00:00
|
|
|
}
|
1999-09-10 08:47:12 +00:00
|
|
|
}
|
|
|
|
}
|
1999-09-09 01:07:06 +00:00
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
PRBool
|
2001-12-04 22:32:49 +00:00
|
|
|
nsPopupSetFrame::OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
|
1999-09-10 08:47:12 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsMouseEvent event;
|
2002-03-27 02:59:39 +00:00
|
|
|
event.eventStructType = NS_POPUP_EVENT;
|
2001-08-06 21:49:35 +00:00
|
|
|
event.message = NS_XUL_POPUP_SHOWING;
|
2000-01-16 17:06:08 +00:00
|
|
|
event.isShift = PR_FALSE;
|
|
|
|
event.isControl = PR_FALSE;
|
|
|
|
event.isAlt = PR_FALSE;
|
|
|
|
event.isMeta = PR_FALSE;
|
2000-01-15 17:25:14 +00:00
|
|
|
event.clickCount = 0;
|
|
|
|
event.widget = nsnull;
|
2001-12-04 22:32:49 +00:00
|
|
|
event.point.x = aX;
|
|
|
|
event.point.y = aY;
|
1999-09-10 08:47:12 +00:00
|
|
|
|
|
|
|
if (aPopupContent) {
|
2000-06-29 02:02:43 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
nsresult rv = mPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
|
|
|
rv = shell->HandleDOMEventWithTarget(aPopupContent, &event, &status);
|
|
|
|
}
|
2001-03-21 08:15:49 +00:00
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
|
|
|
|
return PR_FALSE;
|
2001-03-21 08:15:49 +00:00
|
|
|
|
|
|
|
// The menu is going to show, and the create handler has executed.
|
|
|
|
// We should now walk all of our menu item children, checking to see if any
|
|
|
|
// of them has a command attribute. If so, then several attributes must
|
|
|
|
// potentially be updated.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
aPopupContent->GetDocument(*getter_AddRefs(doc));
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
|
|
|
|
|
|
|
|
PRInt32 count;
|
|
|
|
aPopupContent->ChildCount(count);
|
|
|
|
for (PRInt32 i = 0; i < count; i++) {
|
|
|
|
nsCOMPtr<nsIContent> grandChild;
|
|
|
|
aPopupContent->ChildAt(i, *getter_AddRefs(grandChild));
|
|
|
|
nsCOMPtr<nsIAtom> tag;
|
|
|
|
grandChild->GetTag(*getter_AddRefs(tag));
|
|
|
|
if (tag.get() == nsXULAtoms::menuitem) {
|
|
|
|
// See if we have a command attribute.
|
|
|
|
nsAutoString command;
|
2001-08-17 08:14:14 +00:00
|
|
|
grandChild->GetAttr(kNameSpaceID_None, nsXULAtoms::command, command);
|
2001-03-21 08:15:49 +00:00
|
|
|
if (!command.IsEmpty()) {
|
|
|
|
// We do! Look it up in our document
|
|
|
|
nsCOMPtr<nsIDOMElement> commandElt;
|
|
|
|
domDoc->GetElementById(command, getter_AddRefs(commandElt));
|
|
|
|
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
|
2001-03-23 02:56:24 +00:00
|
|
|
if ( commandContent ) {
|
|
|
|
nsAutoString commandDisabled, menuDisabled;
|
2001-08-17 08:14:14 +00:00
|
|
|
commandContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, commandDisabled);
|
|
|
|
grandChild->GetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, menuDisabled);
|
2001-03-23 02:56:24 +00:00
|
|
|
if (!commandDisabled.Equals(menuDisabled)) {
|
|
|
|
// The menu's disabled state needs to be updated to match the command.
|
|
|
|
if (commandDisabled.IsEmpty())
|
2001-08-17 08:14:14 +00:00
|
|
|
grandChild->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, PR_TRUE);
|
|
|
|
else grandChild->SetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, commandDisabled, PR_TRUE);
|
2001-03-23 02:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString commandValue, menuValue;
|
2001-08-17 08:14:14 +00:00
|
|
|
commandContent->GetAttr(kNameSpaceID_None, nsXULAtoms::label, commandValue);
|
|
|
|
grandChild->GetAttr(kNameSpaceID_None, nsXULAtoms::label, menuValue);
|
2001-03-23 02:56:24 +00:00
|
|
|
if (!commandValue.Equals(menuValue)) {
|
|
|
|
// The menu's value state needs to be updated to match the command.
|
|
|
|
// Note that (unlike the disabled state) if the command has *no* value, we
|
|
|
|
// assume the menu is supplying its own.
|
|
|
|
if (!commandValue.IsEmpty())
|
2001-08-17 08:14:14 +00:00
|
|
|
grandChild->SetAttr(kNameSpaceID_None, nsXULAtoms::label, commandValue, PR_TRUE);
|
2001-03-23 02:56:24 +00:00
|
|
|
}
|
2002-02-13 04:14:26 +00:00
|
|
|
|
|
|
|
// The menu's accesskey needs to be updated to match the command.
|
|
|
|
// If the command has no accesskey, assume the menu is supplying its own.
|
|
|
|
commandContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::accesskey, commandValue);
|
|
|
|
grandChild->GetAttr(kNameSpaceID_None, nsHTMLAtoms::accesskey, menuValue);
|
|
|
|
if (!commandValue.Equals(menuValue)) {
|
|
|
|
if (!commandValue.IsEmpty())
|
|
|
|
grandChild->SetAttr(kNameSpaceID_None, nsHTMLAtoms::accesskey, commandValue, PR_TRUE);
|
|
|
|
}
|
2001-03-21 08:15:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-09-10 08:47:12 +00:00
|
|
|
}
|
1999-09-09 01:07:06 +00:00
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
return PR_TRUE;
|
1999-09-09 02:55:56 +00:00
|
|
|
}
|
1999-09-10 08:47:12 +00:00
|
|
|
|
2001-08-06 21:49:35 +00:00
|
|
|
PRBool
|
2001-12-04 22:32:49 +00:00
|
|
|
nsPopupSetFrame::OnCreated(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
|
2001-08-06 21:49:35 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsMouseEvent event;
|
2002-03-27 02:59:39 +00:00
|
|
|
event.eventStructType = NS_POPUP_EVENT;
|
2001-08-06 21:49:35 +00:00
|
|
|
event.message = NS_XUL_POPUP_SHOWN;
|
|
|
|
event.isShift = PR_FALSE;
|
|
|
|
event.isControl = PR_FALSE;
|
|
|
|
event.isAlt = PR_FALSE;
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.clickCount = 0;
|
|
|
|
event.widget = nsnull;
|
2001-12-04 22:32:49 +00:00
|
|
|
event.point.x = aX;
|
|
|
|
event.point.y = aY;
|
2001-08-06 21:49:35 +00:00
|
|
|
|
|
|
|
if (aPopupContent) {
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
nsresult rv = mPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
|
|
|
rv = shell->HandleDOMEventWithTarget(aPopupContent, &event, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-09-10 08:47:12 +00:00
|
|
|
PRBool
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::OnDestroy(nsIContent* aPopupContent)
|
1999-09-10 08:47:12 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsMouseEvent event;
|
2002-03-27 02:59:39 +00:00
|
|
|
event.eventStructType = NS_POPUP_EVENT;
|
2001-08-06 21:49:35 +00:00
|
|
|
event.message = NS_XUL_POPUP_HIDING;
|
|
|
|
event.isShift = PR_FALSE;
|
|
|
|
event.isControl = PR_FALSE;
|
|
|
|
event.isAlt = PR_FALSE;
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.clickCount = 0;
|
|
|
|
event.widget = nsnull;
|
2001-08-18 01:04:47 +00:00
|
|
|
|
|
|
|
if (aPopupContent) {
|
2001-08-06 21:49:35 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
nsresult rv = mPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
2001-08-18 01:04:47 +00:00
|
|
|
rv = shell->HandleDOMEventWithTarget(aPopupContent, &event, &status);
|
2001-08-06 21:49:35 +00:00
|
|
|
}
|
|
|
|
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::OnDestroyed(nsIContent* aPopupContent)
|
2001-08-06 21:49:35 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsMouseEvent event;
|
2002-03-27 02:59:39 +00:00
|
|
|
event.eventStructType = NS_POPUP_EVENT;
|
2001-08-06 21:49:35 +00:00
|
|
|
event.message = NS_XUL_POPUP_HIDDEN;
|
2000-01-16 17:06:08 +00:00
|
|
|
event.isShift = PR_FALSE;
|
|
|
|
event.isControl = PR_FALSE;
|
|
|
|
event.isAlt = PR_FALSE;
|
|
|
|
event.isMeta = PR_FALSE;
|
2000-01-15 17:25:14 +00:00
|
|
|
event.clickCount = 0;
|
|
|
|
event.widget = nsnull;
|
1999-09-10 08:47:12 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
if (aPopupContent) {
|
2000-06-29 02:02:43 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
nsresult rv = mPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
2001-08-18 01:04:47 +00:00
|
|
|
rv = shell->HandleDOMEventWithTarget(aPopupContent, &event, &status);
|
2000-06-29 02:02:43 +00:00
|
|
|
}
|
1999-09-10 08:47:12 +00:00
|
|
|
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-09-25 03:39:35 +00:00
|
|
|
void
|
|
|
|
nsPopupSetFrame::UpdateDismissalListener(nsIMenuParent* aMenuParent)
|
|
|
|
{
|
2001-09-10 07:34:54 +00:00
|
|
|
if (!nsMenuFrame::sDismissalListener) {
|
1999-09-25 03:39:35 +00:00
|
|
|
if (!aMenuParent)
|
|
|
|
return;
|
|
|
|
// Create the listener and attach it to the outermost window.
|
|
|
|
aMenuParent->CreateDismissalListener();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the menu dismissal listener knows what the current
|
|
|
|
// innermost menu popup frame is.
|
2001-09-10 07:34:54 +00:00
|
|
|
nsMenuFrame::sDismissalListener->SetCurrentMenuParent(aMenuParent);
|
1999-09-25 03:39:35 +00:00
|
|
|
}
|
2000-08-17 09:15:51 +00:00
|
|
|
|
2001-09-22 00:32:23 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup)
|
|
|
|
{
|
|
|
|
// This was called by the Destroy() method of the popup, so all we have to do is
|
|
|
|
// get the popup out of our list, so we don't reflow it later.
|
|
|
|
nsPopupFrameList* currEntry = mPopupList;
|
|
|
|
nsPopupFrameList* temp = nsnull;
|
|
|
|
while (currEntry) {
|
|
|
|
if (currEntry->mPopupFrame == aPopup) {
|
|
|
|
// Remove this entry.
|
|
|
|
if (temp)
|
|
|
|
temp->mNextPopup = currEntry->mNextPopup;
|
|
|
|
else
|
|
|
|
mPopupList = currEntry->mNextPopup;
|
|
|
|
|
|
|
|
// Destroy the frame.
|
|
|
|
currEntry->mPopupFrame->Destroy(mPresContext);
|
|
|
|
|
|
|
|
// Delete the entry.
|
|
|
|
currEntry->mNextPopup = nsnull;
|
|
|
|
delete currEntry;
|
|
|
|
|
|
|
|
// Break out of the loop.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
temp = currEntry;
|
|
|
|
currEntry = currEntry->mNextPopup;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-08-17 09:15:51 +00:00
|
|
|
NS_IMETHODIMP
|
2001-08-18 01:04:47 +00:00
|
|
|
nsPopupSetFrame::AddPopupFrame(nsIFrame* aPopup)
|
2000-08-17 09:15:51 +00:00
|
|
|
{
|
2001-08-18 01:04:47 +00:00
|
|
|
// The entry should already exist, but might not (if someone decided to make their
|
|
|
|
// popup visible straightaway, e.g., the autocomplete widget).
|
2000-08-17 09:15:51 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// First look for an entry by content.
|
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
aPopup->GetContent(getter_AddRefs(content));
|
|
|
|
nsPopupFrameList* entry = nsnull;
|
|
|
|
if (mPopupList)
|
|
|
|
entry = mPopupList->GetEntry(content);
|
|
|
|
if (!entry) {
|
|
|
|
entry = new nsPopupFrameList(content, mPopupList);
|
|
|
|
mPopupList = entry;
|
2000-08-24 03:58:42 +00:00
|
|
|
}
|
2000-08-17 09:15:51 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// Set the frame connection.
|
|
|
|
entry->mPopupFrame = aPopup;
|
2000-08-17 09:15:51 +00:00
|
|
|
|
2001-08-18 01:04:47 +00:00
|
|
|
// Now return. The remaining entry values will be filled in if/when showPopup is
|
|
|
|
// called for this popup.
|
2000-08-17 09:15:51 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-08-18 01:04:47 +00:00
|
|
|
|