Bug 450767 - Don't necessarily apply Aero Glass to the entire window r=jimm sr=roc

This commit is contained in:
Rob Arnold 2010-03-17 18:56:00 -04:00
parent a3ed1e1465
commit 5c251e360c
7 changed files with 108 additions and 17 deletions

View File

@ -42,6 +42,8 @@
#include "nsRect.h"
#include "nsPoint.h"
class nsIntRegion;
/**
* Implementation of regions.
* A region is represented as circular double-linked list of nsRegion::RgnRect structures.
@ -176,6 +178,7 @@ public:
PRBool IsEqual (const nsRegion& aRegion) const;
PRUint32 GetNumRects () const { return mRectCount; }
const nsRect& GetBounds () const { return mBoundRect; }
nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const;
/**
* Make sure the region has at most aMaxRects by adding area to it

View File

@ -1288,6 +1288,17 @@ void nsRegion::MoveBy (nsPoint aPt)
}
}
nsIntRegion nsRegion::ToOutsidePixels(nscoord aAppUnitsPerPixel) const {
nsIntRegion result;
nsRegionRectIterator rgnIter(*this);
const nsRect *currentRect;
while (currentRect = rgnIter.Next()) {
nsIntRect deviceRect = currentRect->ToOutsidePixels(aAppUnitsPerPixel);
result.Or(result, deviceRect);
}
return result;
}
void nsRegion::SimplifyOutward (PRUint32 aMaxRects)
{
NS_ASSERTION(aMaxRects >= 1, "Invalid max rect count");

View File

@ -1229,6 +1229,12 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
PRUint32 flags = nsDisplayList::PAINT_DEFAULT;
if (aFlags & PAINT_WIDGET_LAYERS) {
flags |= nsDisplayList::PAINT_USE_WIDGET_LAYERS;
nsIWidget *widget = aFrame->GetWindow();
PRInt32 pixelRatio = widget->GetDeviceContext()->AppUnitsPerDevPixel();
nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(pixelRatio));
nsIntRegion dirtyWindowRegion(aDirtyRegion.ToOutsidePixels(pixelRatio));
widget->UpdatePossiblyTransparentRegion(dirtyWindowRegion, visibleWindowRegion);
}
list.Paint(&builder, aRenderingContext, flags);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion

View File

@ -43,6 +43,7 @@
#include "nsCoord.h"
#include "nsRect.h"
#include "nsPoint.h"
#include "nsRegion.h"
#include "prthread.h"
#include "nsEvent.h"
@ -588,6 +589,16 @@ 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
*/
virtual void UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion,
const nsIntRegion &aPossiblyTransparentRegion) {};
/**
* This represents a command to set the bounds and clip region of
* a child widget.

View File

@ -37,6 +37,8 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __UXThemeData_h__
#define __UXThemeData_h__
#include <windows.h>
#include <uxtheme.h>
@ -190,3 +192,4 @@ public:
}
#endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
};
#endif // __UXThemeData_h__

View File

@ -168,7 +168,6 @@
#include "gfxWindowsPlatform.h"
#if !defined(WINCE)
#include "nsUXThemeData.h"
#include "nsUXThemeConstants.h"
#include "nsKeyboardLayout.h"
#include "nsNativeDragTarget.h"
@ -400,6 +399,9 @@ nsWindow::nsWindow() : nsBaseWidget()
mTransparentSurface = nsnull;
mMemoryDC = nsnull;
mTransparencyMode = eTransparencyOpaque;
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
memset(&mGlassMargins, 0, sizeof mGlassMargins);
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
#endif
mBackground = ::GetSysColor(COLOR_BTNFACE);
mBrush = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
@ -2017,6 +2019,66 @@ void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
{
GetTopLevelWindow(PR_TRUE)->SetWindowTranslucencyInner(aMode);
}
void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion,
const nsIntRegion &aPossiblyTransparentRegion) {
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
if (mTransparencyMode != eTransparencyGlass)
return;
HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE);
nsWindow* topWindow = GetNSWindowPtr(hWnd);
mPossiblyTransparentRegion.Sub(mPossiblyTransparentRegion, aDirtyRegion);
mPossiblyTransparentRegion.Or(mPossiblyTransparentRegion, aPossiblyTransparentRegion);
nsIntRect clientBounds;
topWindow->GetClientBounds(clientBounds);
nsIntRegion opaqueRegion;
opaqueRegion.Sub(clientBounds, mPossiblyTransparentRegion);
MARGINS margins = { 0, 0, 0, 0 };
DWORD_PTR dwStyle = ::GetWindowLongPtrW(hWnd, GWL_STYLE);
// If there is no opaque region or hidechrome=true then full glass
if (opaqueRegion.IsEmpty() || !(dwStyle & WS_CAPTION)) {
margins.cxLeftWidth = -1;
} else {
// Find the largest rectangle and use that to calculate the inset
nsIntRegionRectIterator rgnIter(opaqueRegion);
const nsIntRect *currentRect = rgnIter.Next();
nsIntRect largest = *currentRect;
nscoord largestArea = largest.width * largest.height;
while (currentRect = rgnIter.Next()) {
nscoord area = currentRect->width * currentRect->height;
if (area > largestArea) {
largest = *currentRect;
largestArea = area;
}
}
margins.cxLeftWidth = largest.x;
margins.cxRightWidth = clientBounds.width - largest.XMost();
margins.cyTopHeight = largest.y;
margins.cyBottomHeight = clientBounds.height - largest.YMost();
}
if (memcmp(&mGlassMargins, &margins, sizeof mGlassMargins)) {
mGlassMargins = margins;
UpdateGlass();
}
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
}
void nsWindow::UpdateGlass() {
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE);
DWMNCRENDERINGPOLICY policy = DWMNCRP_USEWINDOWSTYLE;
if(eTransparencyGlass == mTransparencyMode) {
policy = DWMNCRP_ENABLED;
}
if(nsUXThemeData::CheckForCompositor()) {
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd, &mGlassMargins);
nsUXThemeData::dwmSetWindowAttributePtr(hWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy);
}
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
}
#endif
/**************************************************************
@ -4584,10 +4646,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
case WM_DWMCOMPOSITIONCHANGED:
BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
DispatchStandardEvent(NS_THEMECHANGED);
if (nsUXThemeData::CheckForCompositor() && mTransparencyMode == eTransparencyGlass) {
MARGINS margins = { -1, -1, -1, -1 };
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd, &margins);
}
UpdateGlass();
Invalidate(PR_FALSE);
break;
#endif
@ -6692,18 +6751,7 @@ void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode)
mTransparencyMode = aMode;
SetupTranslucentWindowMemoryBitmap(aMode);
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
MARGINS margins = { 0, 0, 0, 0 };
DWMNCRENDERINGPOLICY policy = DWMNCRP_USEWINDOWSTYLE;
if(eTransparencyGlass == aMode) {
margins.cxLeftWidth = -1;
policy = DWMNCRP_ENABLED;
}
if(nsUXThemeData::sHaveCompositor) {
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd, &margins);
nsUXThemeData::dwmSetWindowAttributePtr(hWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy);
}
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
UpdateGlass();
#endif // #ifndef WINCE
}

View File

@ -77,6 +77,9 @@
#include "nsIAccessible.h"
#endif
#if !defined(WINCE)
#include "nsUXThemeData.h"
#endif // !defined(WINCE)
/**
* Forward class definitions
*/
@ -182,6 +185,7 @@ public:
#ifdef MOZ_XUL
virtual void SetTransparencyMode(nsTransparencyMode aMode);
virtual nsTransparencyMode GetTransparencyMode();
virtual void UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, const nsIntRegion& aPossiblyTransparentRegion);
#endif // MOZ_XUL
#ifdef NS_ENABLE_TSF
NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
@ -385,6 +389,7 @@ private:
void ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight, PRBool force = PR_FALSE);
nsresult UpdateTranslucentWindow();
void SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode);
void UpdateGlass();
protected:
#endif // MOZ_XUL
@ -492,6 +497,10 @@ protected:
nsRefPtr<gfxWindowsSurface> mTransparentSurface;
HDC mMemoryDC;
nsTransparencyMode mTransparencyMode;
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
nsIntRegion mPossiblyTransparentRegion;
MARGINS mGlassMargins;
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
#endif // MOZ_XUL
// Win7 Gesture processing and management