From fdb11b09501ab6e07e3d965bf1b67d206f137768 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Thu, 27 Jan 2011 16:58:58 -0600 Subject: [PATCH] Bug 622328 - Fixup widget's UpdateTransparentRegion now that layout's transparent region includes all content. r=roc, a=blocking. --- layout/base/nsLayoutUtils.cpp | 9 ++-- widget/public/nsIWidget.h | 22 +++++--- widget/src/windows/nsWindow.cpp | 90 ++++++++++++++++----------------- widget/src/windows/nsWindow.h | 2 +- 4 files changed, 61 insertions(+), 62 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 8c3ce0857155..7440db47cdc5 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1538,18 +1538,15 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra NS_WARNING("Flushing retained layers!"); flags |= nsDisplayList::PAINT_FLUSH_LAYERS; } else if (widget && !(aFlags & PAINT_DOCUMENT_RELATIVE)) { - // XXX we should simplify this API now that dirtyWindowRegion always - // covers the entire window + nsIWidget_MOZILLA_2_0_BRANCH* widget2 = + static_cast(widget); PRInt32 pixelRatio = presContext->AppUnitsPerDevPixel(); nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(pixelRatio)); - nsIntRegion dirtyWindowRegion(aDirtyRegion.ToOutsidePixels(pixelRatio)); builder.SetFinalTransparentRegion(visibleRegion); - widget->UpdatePossiblyTransparentRegion(dirtyWindowRegion, visibleWindowRegion); + widget2->UpdateTransparentRegion(visibleWindowRegion); // If we're finished building display list items for painting of the outermost // pres shell, notify the widget about any toolbars we've encountered. - nsIWidget_MOZILLA_2_0_BRANCH* widget2 = - static_cast(widget); widget2->UpdateThemeGeometries(builder.GetThemeGeometries()); } } diff --git a/widget/public/nsIWidget.h b/widget/public/nsIWidget.h index a5763f418fbb..ce6578c0568f 100644 --- a/widget/public/nsIWidget.h +++ b/widget/public/nsIWidget.h @@ -123,10 +123,10 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event); { 0xcc443f0b, 0xaf39, 0x415d, \ { 0x9c, 0x4b, 0x7e, 0x06, 0xea, 0xa8, 0xb1, 0x3b } } -// d64532e0-03d6-421c-8e63-da2cff624825 +// {8FC2D005-5359-4dbf-ACB1-701992FB4617} #define NS_IWIDGET_MOZILLA_2_0_BRANCH_IID \ - { 0xd64532e0, 0x03d6, 0x421c, \ - { 0x8e, 0x63, 0xda, 0x2c, 0xff, 0x62, 0x48, 0x25 } } + { 0x8fc2d005, 0x5359, 0x4dbf, \ + { 0xac, 0xb1, 0x70, 0x19, 0x92, 0xfb, 0x46, 0x17 } } /* * Window shadow styles @@ -791,11 +791,7 @@ class nsIWidget : public nsISupports { virtual nsTransparencyMode GetTransparencyMode() = 0; /** - * Updates a region of the window that might not have opaque content drawn. Widgets should - * assume that the initial possibly transparent region is empty. - * - * @param aDirtyRegion the region of the window that aMaybeTransparentRegion pertains to - * @param aPossiblyTransparentRegion the region of the window that is possibly transparent + * depreciated, see 2.0 interface. */ virtual void UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, const nsIntRegion &aPossiblyTransparentRegion) {}; @@ -1434,6 +1430,16 @@ class nsIWidget_MOZILLA_2_0_BRANCH : public nsIWidget { * paint anything. */ virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) = 0; + + /** + * Informs the widget about the region of the window that is partially + * transparent. Widgets should assume that the initial transparent + * region is empty. + * + * @param aTransparentRegion the region of the window that is partially + * transparent. + */ + virtual void UpdateTransparentRegion(const nsIntRegion &aTransparentRegion) {}; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget_MOZILLA_2_0_BRANCH, NS_IWIDGET_MOZILLA_2_0_BRANCH_IID) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 9677095a753e..c478e823ce96 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -376,6 +376,10 @@ static const int MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS = 50; // Windows' glaze effect will start to look stupid. static const int MAX_HORIZONTAL_GLASS_MARGIN = 5; +// 2 pixel offset for eTransparencyBorderlessGlass which equals +// the size of the default window border Windows paints. +static const PRInt32 kGlassMarginAdjustment = 2; + /************************************************************** ************************************************************** ** @@ -2557,63 +2561,66 @@ void nsWindow::SetTransparencyMode(nsTransparencyMode aMode) GetTopLevelWindow(PR_TRUE)->SetWindowTranslucencyInner(aMode); } -static const PRInt32 kGlassMarginAdjustment = 2; +static const nsIntRegion +RegionFromArray(const nsTArray& aRects) +{ + nsIntRegion region; + for (PRUint32 i = 0; i < aRects.Length(); ++i) { + region.Or(region, aRects[i]); + } + return region; +} -void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, - const nsIntRegion &aPossiblyTransparentRegion) { +void nsWindow::UpdateTransparentRegion(const nsIntRegion &aTransparentRegion) +{ #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - if (!HasGlass()) + if (!HasGlass() || GetParent()) return; - HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE); - nsWindow* topWindow = GetNSWindowPtr(hWnd); - - if (GetParent()) - return; - - mPossiblyTransparentRegion.Sub(mPossiblyTransparentRegion, aDirtyRegion); - mPossiblyTransparentRegion.Or(mPossiblyTransparentRegion, aPossiblyTransparentRegion); - nsIntRect clientBounds; - topWindow->GetClientBounds(clientBounds); + GetClientBounds(clientBounds); + + // calculate the known fully opaque region by subtracting the transparent + // areas from client bounds. We'll use this to calculate our new glass + // bounds. nsIntRegion opaqueRegion; - opaqueRegion.Sub(clientBounds, mPossiblyTransparentRegion); - - MARGINS margins = { 0, 0, 0, 0 }; - DWORD_PTR dwStyle = ::GetWindowLongPtrW(hWnd, GWL_STYLE); + opaqueRegion.Sub(clientBounds, aTransparentRegion); // If there is no opaque region or hidechrome=true, set margins - // to support a full sheet of glass. - // Comments in MSDN indicate all values must be set to -1 to get a full - // sheet of glass. - margins.cxLeftWidth = margins.cxRightWidth = - margins.cyTopHeight = margins.cyBottomHeight = -1; + // to support a full sheet of glass. Comments in MSDN indicate + // all values must be set to -1 to get a full sheet of glass. + MARGINS margins = { -1, -1, -1, -1 }; + bool visiblePlugin = false; if (!opaqueRegion.IsEmpty() && !mHideChrome) { nsIntRect pluginBounds; for (nsIWidget* child = GetFirstChild(); child; child = child->GetNextSibling()) { nsWindowType type; child->GetWindowType(type); if (type == eWindowType_plugin) { + // Collect the bounds of all plugins for GetLargestRectangle. nsIntRect childBounds; child->GetBounds(childBounds); - if (mTransparencyMode == eTransparencyBorderlessGlass) { - // We shrink the margins by kGlassMarginAdjustment in UpdateGlass. - // So here, try to ensure that the shrunk margin will still contain - // the plugin bounds. Of course there's no guarantee that we'll - // find an opaque rectangle including this enlarged area, for example - // if the plugin is already at the edge of the window. - childBounds.Inflate(kGlassMarginAdjustment, kGlassMarginAdjustment); - } pluginBounds.UnionRect(pluginBounds, childBounds); + // Detect if any region of a plugin is visible. + nsTArray currentRects; + child->GetWindowClipRegion(¤tRects); + nsIntRegion currentClipRegion = RegionFromArray(currentRects); + nsIntRect bounds = currentClipRegion.GetBounds(); + if (!bounds.IsEmpty()) { + visiblePlugin = true; + } } } // Find the largest rectangle and use that to calculate the inset. Our top // priority is to include the bounds of all plugins. + // Also don't let MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS override content + // that contains a visible plugin since glass over plugins looks bad. nsIntRect largest = opaqueRegion.GetLargestRectangle(pluginBounds); - if (largest.x <= MAX_HORIZONTAL_GLASS_MARGIN && - clientBounds.width - largest.XMost() <= MAX_HORIZONTAL_GLASS_MARGIN && - largest.height >= MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS) { + if (visiblePlugin || + (largest.x <= MAX_HORIZONTAL_GLASS_MARGIN && + clientBounds.width - largest.XMost() <= MAX_HORIZONTAL_GLASS_MARGIN && + largest.height >= MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS)) { margins.cxLeftWidth = largest.x; margins.cxRightWidth = clientBounds.width - largest.XMost(); margins.cyBottomHeight = clientBounds.height - largest.YMost(); @@ -2639,7 +2646,6 @@ void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, void nsWindow::UpdateGlass() { #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE); MARGINS margins = mGlassMargins; // DWMNCRP_USEWINDOWSTYLE - The non-client rendering area is @@ -2675,8 +2681,8 @@ void nsWindow::UpdateGlass() // Extends the window frame behind the client area if(nsUXThemeData::CheckForCompositor()) { - nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd, &margins); - nsUXThemeData::dwmSetWindowAttributePtr(hWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy); + nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd, &margins); + nsUXThemeData::dwmSetWindowAttributePtr(mWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy); } #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN } @@ -7312,16 +7318,6 @@ CreateHRGNFromArray(const nsTArray& aRects) return ::ExtCreateRegion(NULL, buf.Length(), data); } -static const nsIntRegion -RegionFromArray(const nsTArray& aRects) -{ - nsIntRegion region; - for (PRUint32 i = 0; i < aRects.Length(); ++i) { - region.Or(region, aRects[i]); - } - return region; -} - static const nsTArray ArrayFromRegion(const nsIntRegion& aRegion) { diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index e6141f0cc6e9..1115a4f37b75 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -196,7 +196,7 @@ public: #ifdef MOZ_XUL virtual void SetTransparencyMode(nsTransparencyMode aMode); virtual nsTransparencyMode GetTransparencyMode(); - virtual void UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, const nsIntRegion& aPossiblyTransparentRegion); + virtual void UpdateTransparentRegion(const nsIntRegion& aTransparentRegion); #endif // MOZ_XUL #ifdef NS_ENABLE_TSF NS_IMETHOD OnIMEFocusChange(PRBool aFocus);