mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 326877, close popups when navigating pages, r+sr=bz
This commit is contained in:
parent
8a39ba9ca2
commit
42cfbd51a9
@ -120,6 +120,7 @@
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsIMenuParent.h"
|
||||
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
@ -370,6 +371,8 @@ private:
|
||||
nsresult GetPopupLinkNode(nsIDOMNode** aNode);
|
||||
nsresult GetPopupImageNode(nsIImageLoadingContent** aNode);
|
||||
|
||||
void HideViewIfPopup(nsIView* aView);
|
||||
|
||||
void DumpContentToPPM(const char* aFileName);
|
||||
|
||||
void PrepareToStartLoad(void);
|
||||
@ -1247,36 +1250,69 @@ DocumentViewerImpl::PageHide(PRBool aIsUnload)
|
||||
}
|
||||
|
||||
mDocument->OnPageHide(!aIsUnload);
|
||||
if (!aIsUnload)
|
||||
return NS_OK;
|
||||
if (aIsUnload) {
|
||||
// if Destroy() was called during OnPageHide(), mDocument is nsnull.
|
||||
NS_ENSURE_STATE(mDocument);
|
||||
|
||||
// if Destroy() was called during OnPageHide(), mDocument is nsnull.
|
||||
NS_ENSURE_STATE(mDocument);
|
||||
// First, get the window from the document...
|
||||
nsPIDOMWindow *window = mDocument->GetWindow();
|
||||
|
||||
// First, get the window from the document...
|
||||
nsPIDOMWindow *window = mDocument->GetWindow();
|
||||
if (!window) {
|
||||
// Fail if no window is available...
|
||||
NS_ERROR("window not set for document!");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (!window) {
|
||||
// Fail if no window is available...
|
||||
NS_ERROR("window not set for document!");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// Now, fire an Unload event to the document...
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent event(PR_TRUE, NS_PAGE_UNLOAD);
|
||||
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
// XXX Dispatching to |window|, but using |document| as the target.
|
||||
event.target = mDocument;
|
||||
|
||||
// Never permit popups from the unload handler, no matter how we get
|
||||
// here.
|
||||
nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
|
||||
|
||||
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
|
||||
}
|
||||
|
||||
// Now, fire an Unload event to the document...
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent event(PR_TRUE, NS_PAGE_UNLOAD);
|
||||
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
// XXX Dispatching to |window|, but using |document| as the target.
|
||||
event.target = mDocument;
|
||||
if (mPresShell) {
|
||||
// look for open menupopups and close them after the unload event, in case
|
||||
// the unload event listeners open any new popups
|
||||
nsIViewManager *vm = mPresShell->GetViewManager();
|
||||
if (vm) {
|
||||
nsIView *rootView = nsnull;
|
||||
vm->GetRootView(rootView);
|
||||
if (rootView)
|
||||
HideViewIfPopup(rootView);
|
||||
}
|
||||
}
|
||||
|
||||
// Never permit popups from the unload handler, no matter how we get
|
||||
// here.
|
||||
nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
|
||||
|
||||
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
DocumentViewerImpl::HideViewIfPopup(nsIView* aView)
|
||||
{
|
||||
nsIFrame* frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
|
||||
if (frame) {
|
||||
nsIMenuParent* parent;
|
||||
CallQueryInterface(frame, &parent);
|
||||
if (parent) {
|
||||
parent->HideChain();
|
||||
// really make sure the view is hidden
|
||||
mViewManager->SetViewVisibility(aView, nsViewVisibility_kHide);
|
||||
}
|
||||
}
|
||||
|
||||
nsIView* child = aView->GetFirstChild();
|
||||
while (child) {
|
||||
HideViewIfPopup(child);
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AttachContainerRecurse(nsIDocShell* aShell)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsMenuBarListener.h"
|
||||
#include "nsPopupSetFrame.h"
|
||||
|
||||
class nsMenuBoxObject : public nsIMenuBoxObject, public nsBoxObject
|
||||
{
|
||||
@ -92,6 +93,9 @@ NS_IMETHODIMP nsMenuBoxObject::OpenMenu(PRBool aOpenFlag)
|
||||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
if (!nsPopupSetFrame::MayOpenPopup(frame))
|
||||
return NS_OK;
|
||||
|
||||
nsIMenuFrame* menuFrame;
|
||||
CallQueryInterface(frame, &menuFrame);
|
||||
if (!menuFrame)
|
||||
|
@ -66,6 +66,12 @@
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIRootBox.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
|
||||
#define NS_MENU_POPUP_LIST_INDEX 0
|
||||
|
||||
@ -363,6 +369,9 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
|
||||
const nsString& aPopupType, const nsString& anAnchorAlignment,
|
||||
const nsString& aPopupAlignment)
|
||||
{
|
||||
if (!MayOpenPopup(this))
|
||||
return NS_OK;
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
// First fire the popupshowing event.
|
||||
if (!OnCreate(aXPos, aYPos, aPopupContent) || !weakFrame.IsAlive())
|
||||
@ -825,3 +834,42 @@ nsPopupSetFrame::AddPopupFrame(nsIFrame* aPopup)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//static
|
||||
PRBool
|
||||
nsPopupSetFrame::MayOpenPopup(nsIFrame* aFrame)
|
||||
{
|
||||
nsCOMPtr<nsISupports> cont = aFrame->GetPresContext()->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
|
||||
if (!dsti)
|
||||
return PR_FALSE;
|
||||
|
||||
// chrome shells can always open popups
|
||||
PRInt32 type = -1;
|
||||
if (NS_SUCCEEDED(dsti->GetItemType(&type)) && type == nsIDocShellTreeItem::typeChrome)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> shell = do_QueryInterface(dsti);
|
||||
if (!shell)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(shell);
|
||||
if (!win)
|
||||
return PR_FALSE;
|
||||
|
||||
// only allow popups in active windows
|
||||
PRBool active;
|
||||
nsIFocusController* focusController = win->GetRootFocusController();
|
||||
focusController->GetActive(&active);
|
||||
if (!active)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(shell);
|
||||
if (!baseWin)
|
||||
return PR_FALSE;
|
||||
|
||||
// only allow popups in visible frames
|
||||
PRBool visible;
|
||||
baseWin->GetVisibility(&visible);
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,13 @@ public:
|
||||
void ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag);
|
||||
void OpenPopup(nsPopupFrameList* aEntry, PRBool aOpenFlag);
|
||||
|
||||
/**
|
||||
* Return true if the docshell containing aFrame may open a popup. aFrame
|
||||
* doesn't need to be any particular type of frame, just a frame in the
|
||||
* same document.
|
||||
*/
|
||||
static PRBool MayOpenPopup(nsIFrame* aFrame);
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user