Bug 113232. Make 'background:transparent' work on top-level XUL windows. r=pavlov,kmcclusk,bzbarsky,sr=bzbarsky

This commit is contained in:
roc+%cs.cmu.edu 2003-03-24 04:57:22 +00:00
parent 3dace14ed6
commit 4f81dc78d1
7 changed files with 141 additions and 35 deletions

View File

@ -100,7 +100,7 @@ public:
GetAlphas computes an array of alpha values for a rectangle of pixels, using
the drawn-onto-black and the drawn-onto-white images. The pixels are
returned in a new'ed array of aRect.width*aRect.height elements, in row-major
order. This array must be freed by the caller.
order. This array must be freed by the caller with delete[].
*/
NS_IMETHOD GetAlphas(const nsRect& aRect, nsDrawingSurface aBlack,
nsDrawingSurface aWhite, PRUint8** aAlphas) = 0;

View File

@ -2610,14 +2610,32 @@ nsCSSRendering::FindNonTransparentBackground(nsStyleContext* aContext,
* canvas.
*/
inline PRBool
IsCanvasFrame(nsIFrame *aFrame)
// Returns nsnull if aFrame is not a canvas frame.
// Otherwise, it returns the frame we should look for the background on.
// This is normally aFrame but if aFrame is the viewport, we need to
// look for the background starting at the scroll root (which shares
// style context with the document root) or the document root itself.
// We need to treat the viewport as canvas because, even though
// it does not actually paint a background, we need to get the right
// background style so we correctly detect transparent documents.
inline nsIFrame*
IsCanvasFrame(nsIPresContext* aPresContext, nsIFrame *aFrame)
{
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
return (frameType == nsLayoutAtoms::canvasFrame ||
frameType == nsLayoutAtoms::rootFrame ||
frameType == nsLayoutAtoms::pageFrame);
if (frameType == nsLayoutAtoms::canvasFrame ||
frameType == nsLayoutAtoms::rootFrame ||
frameType == nsLayoutAtoms::pageFrame) {
return aFrame;
} else if (frameType == nsLayoutAtoms::viewportFrame) {
nsIFrame* firstChild;
aFrame->FirstChild(aPresContext, nsnull, &firstChild);
if (firstChild) {
return firstChild;
}
}
return nsnull;
}
inline PRBool
@ -2714,7 +2732,7 @@ FindElementBackground(nsIPresContext* aPresContext,
nsIFrame *parentFrame;
aForFrame->GetParent(&parentFrame);
// XXXldb We shouldn't have to null-check |parentFrame| here.
if (parentFrame && IsCanvasFrame(parentFrame)) {
if (parentFrame && IsCanvasFrame(aPresContext, parentFrame) == parentFrame) {
// Check that we're really the root (rather than in another child list).
nsIFrame *childFrame;
parentFrame->FirstChild(aPresContext, nsnull, &childFrame);
@ -2756,10 +2774,10 @@ nsCSSRendering::FindBackground(nsIPresContext* aPresContext,
const nsStyleBackground** aBackground,
PRBool* aIsCanvas)
{
PRBool isCanvas = IsCanvasFrame(aForFrame);
*aIsCanvas = isCanvas;
return isCanvas
? FindCanvasBackground(aPresContext, aForFrame, aBackground)
nsIFrame* canvasFrame = IsCanvasFrame(aPresContext, aForFrame);
*aIsCanvas = canvasFrame != nsnull;
return canvasFrame
? FindCanvasBackground(aPresContext, canvasFrame, aBackground)
: FindElementBackground(aPresContext, aForFrame, aBackground);
}
@ -2831,11 +2849,21 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
vm->GetRootView(rootView);
nsIView* rootParent;
rootView->GetParent(rootParent);
if (nsnull == rootParent) {
// Ensure that we always paint a color for the root (in case there's
// no background at all or a partly transparent image).
canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor);
if (!rootParent) {
PRBool widgetIsTranslucent = PR_FALSE;
nsCOMPtr<nsIWidget> rootWidget;
rootView->GetWidget(*getter_AddRefs(rootWidget));
if (rootWidget) {
rootWidget->GetWindowTranslucency(widgetIsTranslucent);
}
if (!widgetIsTranslucent) {
// Ensure that we always paint a color for the root (in case there's
// no background at all or a partly transparent image).
canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor);
}
}
}

View File

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsContainerFrame.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsStyleContext.h"
@ -558,15 +559,41 @@ SyncFrameViewGeometryDependentProperties(nsIPresContext* aPresContext,
(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) ||
!aFrame->CanPaintBackground() ||
HasNonZeroBorderRadius(aStyleContext);
if (isCanvas && viewHasTransparentContent) {
if (isCanvas) {
nsIView* rootView;
vm->GetRootView(rootView);
nsIView* rootParent;
rootView->GetParent(rootParent);
if (nsnull == rootParent) {
if (!rootParent) {
viewHasTransparentContent = PR_FALSE;
// We need to set window translucency for top-level windows
// which have transparent backgrounds
if (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) {
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsCOMPtr<nsIDocument> doc;
shell->GetDocument(getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIDocument> parentDoc;
doc->GetParentDocument(getter_AddRefs(parentDoc));
if (!parentDoc) {
// our document is the root of the doc tree, so we must
// either be a top-level XUL window or something embedded.
// The SetWindowTranslucency call will fail if we're embedded.
nsCOMPtr<nsIWidget> widget;
aView->GetWidget(*getter_AddRefs(widget));
if (widget) {
// Enable translucency in the widget
widget->SetWindowTranslucency(PR_TRUE);
viewHasTransparentContent = PR_TRUE;
}
}
}
}
}
}
// XXX we should also set widget transparency for XUL popups that ask for it
const nsStyleDisplay* display;
::GetStyleData(aStyleContext, &display);

View File

@ -2610,14 +2610,32 @@ nsCSSRendering::FindNonTransparentBackground(nsStyleContext* aContext,
* canvas.
*/
inline PRBool
IsCanvasFrame(nsIFrame *aFrame)
// Returns nsnull if aFrame is not a canvas frame.
// Otherwise, it returns the frame we should look for the background on.
// This is normally aFrame but if aFrame is the viewport, we need to
// look for the background starting at the scroll root (which shares
// style context with the document root) or the document root itself.
// We need to treat the viewport as canvas because, even though
// it does not actually paint a background, we need to get the right
// background style so we correctly detect transparent documents.
inline nsIFrame*
IsCanvasFrame(nsIPresContext* aPresContext, nsIFrame *aFrame)
{
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
return (frameType == nsLayoutAtoms::canvasFrame ||
frameType == nsLayoutAtoms::rootFrame ||
frameType == nsLayoutAtoms::pageFrame);
if (frameType == nsLayoutAtoms::canvasFrame ||
frameType == nsLayoutAtoms::rootFrame ||
frameType == nsLayoutAtoms::pageFrame) {
return aFrame;
} else if (frameType == nsLayoutAtoms::viewportFrame) {
nsIFrame* firstChild;
aFrame->FirstChild(aPresContext, nsnull, &firstChild);
if (firstChild) {
return firstChild;
}
}
return nsnull;
}
inline PRBool
@ -2714,7 +2732,7 @@ FindElementBackground(nsIPresContext* aPresContext,
nsIFrame *parentFrame;
aForFrame->GetParent(&parentFrame);
// XXXldb We shouldn't have to null-check |parentFrame| here.
if (parentFrame && IsCanvasFrame(parentFrame)) {
if (parentFrame && IsCanvasFrame(aPresContext, parentFrame) == parentFrame) {
// Check that we're really the root (rather than in another child list).
nsIFrame *childFrame;
parentFrame->FirstChild(aPresContext, nsnull, &childFrame);
@ -2756,10 +2774,10 @@ nsCSSRendering::FindBackground(nsIPresContext* aPresContext,
const nsStyleBackground** aBackground,
PRBool* aIsCanvas)
{
PRBool isCanvas = IsCanvasFrame(aForFrame);
*aIsCanvas = isCanvas;
return isCanvas
? FindCanvasBackground(aPresContext, aForFrame, aBackground)
nsIFrame* canvasFrame = IsCanvasFrame(aPresContext, aForFrame);
*aIsCanvas = canvasFrame != nsnull;
return canvasFrame
? FindCanvasBackground(aPresContext, canvasFrame, aBackground)
: FindElementBackground(aPresContext, aForFrame, aBackground);
}
@ -2831,11 +2849,21 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
vm->GetRootView(rootView);
nsIView* rootParent;
rootView->GetParent(rootParent);
if (nsnull == rootParent) {
// Ensure that we always paint a color for the root (in case there's
// no background at all or a partly transparent image).
canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor);
if (!rootParent) {
PRBool widgetIsTranslucent = PR_FALSE;
nsCOMPtr<nsIWidget> rootWidget;
rootView->GetWidget(*getter_AddRefs(rootWidget));
if (rootWidget) {
rootWidget->GetWindowTranslucency(widgetIsTranslucent);
}
if (!widgetIsTranslucent) {
// Ensure that we always paint a color for the root (in case there's
// no background at all or a partly transparent image).
canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor);
}
}
}

View File

@ -2769,6 +2769,8 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
aWidth, aHeight);
#endif
// ResizeTransparencyBitmap uses the old bounds, so pass it the new bounds
// before we change the old bounds.
ResizeTransparencyBitmap(aWidth, aHeight);
mBounds.width = aWidth;
@ -4421,10 +4423,10 @@ NS_IMETHODIMP nsWindow::UpdateTranslucentWindowAlpha(const nsRect& aRect, PRUint
NS_ASSERTION(mIsTranslucent, "Window is not transparent");
if (mTransparencyBitmap == nsnull) {
if (!mTransparencyBitmap) {
PRInt32 size = ((mBounds.width+7)/8)*mBounds.height;
mTransparencyBitmap = new gchar[size];
if (mTransparencyBitmap == nsnull)
if (!mTransparencyBitmap)
return NS_ERROR_FAILURE;
memset(mTransparencyBitmap, 255, size);
}

View File

@ -874,6 +874,7 @@ void nsXULWindow::OnChromeLoaded()
LoadSizeStateFromXUL();
//LoadContentAreas();
LoadChromeHidingFromXUL();
if (mCenterAfterLoad && !positionSet)
Center(parentWindow, parentWindow ? PR_FALSE : PR_TRUE, PR_FALSE);
@ -883,6 +884,25 @@ void nsXULWindow::OnChromeLoaded()
}
}
nsresult nsXULWindow::LoadChromeHidingFromXUL()
{
NS_ENSURE_STATE(mWindow);
// Get <window> element.
nsCOMPtr<nsIDOMElement> windowElement;
GetWindowDOMElement(getter_AddRefs(windowElement));
NS_ENSURE_TRUE(windowElement, NS_ERROR_FAILURE);
nsAutoString attr;
nsresult rv = windowElement->GetAttribute(NS_LITERAL_STRING("hidechrome"), attr);
if (NS_SUCCEEDED(rv) && attr.EqualsIgnoreCase("true")) {
mWindow->HideWindowChrome(PR_TRUE);
}
return NS_OK;
}
PRBool nsXULWindow::LoadPositionFromXUL()
{
nsresult rv;

View File

@ -80,6 +80,7 @@ protected:
PRBool LoadPositionFromXUL();
PRBool LoadSizeFromXUL();
PRBool LoadSizeStateFromXUL();
nsresult LoadChromeHidingFromXUL();
NS_IMETHOD LoadTitleFromXUL();
NS_IMETHOD LoadWindowClassFromXUL();
NS_IMETHOD LoadIconFromXUL();