From 623f3f1f0bc08b6ab1f5428e4cd4a9589e3404f4 Mon Sep 17 00:00:00 2001 From: "mozilla.mano@sent.com" Date: Wed, 6 Feb 2008 16:55:55 -0800 Subject: [PATCH] Relanding bug 406686 --- content/base/public/nsContentUtils.h | 6 +++ content/base/src/nsContentUtils.cpp | 16 ++++++ dom/src/base/nsGlobalWindow.cpp | 8 +-- gfx/src/thebes/nsThebesImage.cpp | 59 ++++++++++++++++------ layout/base/nsDocumentViewer.cpp | 4 +- layout/generic/nsFrameFrame.cpp | 15 +++++- layout/xul/base/public/nsXULPopupManager.h | 10 +++- layout/xul/base/src/nsXULPopupManager.cpp | 24 +++++++-- 8 files changed, 111 insertions(+), 31 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index f607fcd5c2d8..ca69a77e16f0 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1152,6 +1152,12 @@ public: nsNativeKeyEvent* aNativeEvent, PRBool aGetCharCode); + /** + * Hide any XUL popups associated with aDocument, including any documents + * displayed in child frames. + */ + static void HidePopupsInDocument(nsIDocument* aDocument); + /** * Get the application manifest URI for this context. The manifest URI * is specified in the manifest= attribute of the root element of the diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index c151f3fb5d1a..aa1f8a70de01 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -145,6 +145,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIDOMNSUIEvent.h" #include "nsIDOMNSEvent.h" #include "nsIPrivateDOMEvent.h" +#include "nsXULPopupManager.h" #include "nsIPermissionManager.h" #ifdef IBMBIDI @@ -3924,6 +3925,21 @@ nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMEvent* aDOMEvent, return PR_TRUE; } +/* static */ +void +nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument) +{ + NS_PRECONDITION(aDocument, "Null document"); + + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (pm) { + nsCOMPtr container = aDocument->GetContainer(); + nsCOMPtr docShellToHide = do_QueryInterface(container); + if (docShellToHide) + pm->HidePopupsInDocShell(docShellToHide); + } +} + /* static */ void nsAutoGCRoot::Shutdown() diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index e17612c33075..174ff30d5ba3 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -3297,10 +3297,8 @@ nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32* aWidth, PRInt32* aHeight) #ifdef MOZ_XUL if (!nsContentUtils::IsCallerTrustedForWrite()) { // if attempting to resize the window, hide any open popups - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); nsCOMPtr doc(do_QueryInterface(mDocument)); - if (pm && doc) - pm->HidePopupsInDocument(doc); + nsContentUtils::HidePopupsInDocument(doc); } #endif @@ -3332,10 +3330,8 @@ nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32* aLeft, PRInt32* aTop) if (!nsContentUtils::IsCallerTrustedForWrite()) { #ifdef MOZ_XUL // if attempting to move the window, hide any open popups - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); nsCOMPtr doc(do_QueryInterface(mDocument)); - if (pm && doc) - pm->HidePopupsInDocument(doc); + nsContentUtils::HidePopupsInDocument(doc); #endif PRInt32 screenLeft, screenTop, screenWidth, screenHeight; diff --git a/gfx/src/thebes/nsThebesImage.cpp b/gfx/src/thebes/nsThebesImage.cpp index 864a7d648ed4..d1763d00cf7b 100644 --- a/gfx/src/thebes/nsThebesImage.cpp +++ b/gfx/src/thebes/nsThebesImage.cpp @@ -231,30 +231,57 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext) if (mOptSurface || mSinglePixel) return NS_OK; - if (mWidth == 1 && mHeight == 1) { - // yeah, let's optimize this. - if (mFormat == gfxImageSurface::ImageFormatARGB32 || - mFormat == gfxImageSurface::ImageFormatRGB24) - { - PRUint32 pixel = *((PRUint32 *) mImageSurface->Data()); + /* Figure out if the entire image is a constant color */ - mSinglePixelColor = gfxRGBA - (pixel, - (mFormat == gfxImageSurface::ImageFormatRGB24 ? - gfxRGBA::PACKED_XRGB : - gfxRGBA::PACKED_ARGB_PREMULTIPLIED)); + // this should always be true + if (mStride == mWidth * 4) { + PRUint32 *imgData = (PRUint32*) mImageSurface->Data(); + PRUint32 firstPixel = * (PRUint32*) imgData; + PRUint32 pixelCount = mWidth * mHeight + 1; - mSinglePixel = PR_TRUE; + while (--pixelCount && *imgData++ == firstPixel) + ; - return NS_OK; + if (pixelCount == 0) { + // all pixels were the same + if (mFormat == gfxImageSurface::ImageFormatARGB32 || + mFormat == gfxImageSurface::ImageFormatRGB24) + { + mSinglePixelColor = gfxRGBA + (firstPixel, + (mFormat == gfxImageSurface::ImageFormatRGB24 ? + gfxRGBA::PACKED_XRGB : + gfxRGBA::PACKED_ARGB_PREMULTIPLIED)); + + mSinglePixel = PR_TRUE; + + // XXX we can't do this until we either teach anyone + // who calls GetSurface() about single-color stuff, + // or until we make GetSurface() create a new temporary + // surface to return (and that callers understand that + // modifying that surface won't modify the image). + // Current users are drag & drop and clipboard. +#if 0 + // blow away the older surfaces, to release data + + mImageSurface = nsnull; + mOptSurface = nsnull; +#ifdef XP_WIN + mWinSurface = nsnull; +#endif +#ifdef XP_MACOSX + mQuartzSurface = nsnull; +#endif +#endif + return NS_OK; + } } - // if it's not RGB24/ARGB32, don't optimize, but we should - // never hit this. + // if it's not RGB24/ARGB32, don't optimize, but we never hit this at the moment } // if we're being forced to use image surfaces due to - // resource constraints, don't try to optimize beyond single-pixel. + // resource constraints, don't try to optimize beyond same-pixel. if (ShouldUseImageSurfaces()) return NS_OK; diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 225741fdd330..46c86193d3e8 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1179,9 +1179,7 @@ DocumentViewerImpl::PageHide(PRBool aIsUnload) #ifdef MOZ_XUL // look for open menupopups and close them after the unload event, in case // the unload event listeners open any new popups - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm && mDocument) - pm->HidePopupsInDocument(mDocument); + nsContentUtils::HidePopupsInDocument(mDocument); #endif return NS_OK; diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index 3c010c19c7e6..3b66578af62f 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -21,7 +21,7 @@ * * Contributor(s): * Travis Bogard - * Håkan Waara + * HÂkan Waara * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -94,6 +94,10 @@ #include "nsIObjectLoadingContent.h" #include "nsLayoutUtils.h" +#ifdef MOZ_XUL +#include "nsXULPopupManager.h" +#endif + // For Accessibility #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -673,6 +677,15 @@ nsSubDocumentFrame::AttributeChanged(PRInt32 aNameSpaceID, PRBool is_primary = value.LowerCaseEqualsLiteral("content-primary"); +#ifdef MOZ_XUL + // when a content panel is no longer primary, hide any open popups it may have + if (!is_primary) { + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (pm) + pm->HidePopupsInDocShell(docShellAsItem); + } +#endif + parentTreeOwner->ContentShellRemoved(docShellAsItem); if (value.LowerCaseEqualsLiteral("content") || diff --git a/layout/xul/base/public/nsXULPopupManager.h b/layout/xul/base/public/nsXULPopupManager.h index 7b077f051b7b..1172e6bc3a61 100644 --- a/layout/xul/base/public/nsXULPopupManager.h +++ b/layout/xul/base/public/nsXULPopupManager.h @@ -75,6 +75,7 @@ class nsMenuPopupFrame; class nsMenuBarFrame; class nsIMenuParent; class nsIDOMKeyEvent; +class nsIDocShellTreeItem; enum nsPopupType { ePopupTypePanel, @@ -473,10 +474,10 @@ public: void HidePopupAfterDelay(nsMenuPopupFrame* aPopup); /** - * Hide all of the popups from a given document. This should be called when the + * Hide all of the popups from a given docshell. This should be called when the * document is hidden. */ - void HidePopupsInDocument(nsIDocument* aDocument); + void HidePopupsInDocShell(nsIDocShellTreeItem* aDocShellToHide); /** * Execute a menu command from the triggering event aEvent. @@ -712,6 +713,11 @@ protected: */ void UpdateKeyboardListeners(); + /* + * Returns true if the docshell for aDoc is aExpected or a child of aExpected. + */ + PRBool IsChildOfDocShell(nsIDocument* aDoc, nsIDocShellTreeItem* aExpected); + // the document the key event listener is attached to nsCOMPtr mKeyListener; diff --git a/layout/xul/base/src/nsXULPopupManager.cpp b/layout/xul/base/src/nsXULPopupManager.cpp index 78eddd2339d4..6cc44cf6f2fd 100644 --- a/layout/xul/base/src/nsXULPopupManager.cpp +++ b/layout/xul/base/src/nsXULPopupManager.cpp @@ -60,6 +60,7 @@ #include "nsPIDOMWindow.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIBaseWindow.h" +#include "nsIDocShellTreeItem.h" // See matching definitions in nsXULPopupManager.h nsNavigationDirection DirectionFromKeyCode_lr_tb [6] = { @@ -765,8 +766,25 @@ nsXULPopupManager::HidePopupsInList(const nsTArray &aFrames, SetCaptureState(nsnull); } +PRBool +nsXULPopupManager::IsChildOfDocShell(nsIDocument* aDoc, nsIDocShellTreeItem* aExpected) +{ + nsCOMPtr doc = aDoc->GetContainer(); + nsCOMPtr docShellItem(do_QueryInterface(doc)); + while(docShellItem) { + if (docShellItem == aExpected) + return PR_TRUE; + + nsCOMPtr parent; + docShellItem->GetParent(getter_AddRefs(parent)); + docShellItem = parent; + } + + return PR_FALSE; +} + void -nsXULPopupManager::HidePopupsInDocument(nsIDocument* aDocument) +nsXULPopupManager::HidePopupsInDocShell(nsIDocShellTreeItem* aDocShellToHide) { nsTArray popupsToHide; @@ -775,7 +793,7 @@ nsXULPopupManager::HidePopupsInDocument(nsIDocument* aDocument) while (item) { nsMenuChainItem* parent = item->GetParent(); if (item->Frame()->PopupState() != ePopupInvisible && - aDocument && item->Content()->GetOwnerDoc() == aDocument) { + IsChildOfDocShell(item->Content()->GetOwnerDoc(), aDocShellToHide)) { nsMenuPopupFrame* frame = item->Frame(); item->Detach(&mCurrentMenu); delete item; @@ -789,7 +807,7 @@ nsXULPopupManager::HidePopupsInDocument(nsIDocument* aDocument) while (item) { nsMenuChainItem* parent = item->GetParent(); if (item->Frame()->PopupState() != ePopupInvisible && - aDocument && item->Content()->GetOwnerDoc() == aDocument) { + IsChildOfDocShell(item->Content()->GetOwnerDoc(), aDocShellToHide)) { nsMenuPopupFrame* frame = item->Frame(); item->Detach(&mPanels); delete item;