From e7a8d69a7cdb6f740b40f374b83ab0d674f9a8bd Mon Sep 17 00:00:00 2001 From: Felipe Gomes Date: Fri, 27 Aug 2010 18:26:30 -0300 Subject: [PATCH] Bug 574833. Persona theme with disabled menu bar completely cover aero caption buttons. r=dao r=jmathies a=betaN --- .../themes/winstripe/browser/browser-aero.css | 2 +- widget/src/windows/nsUXThemeData.cpp | 2 + widget/src/windows/nsUXThemeData.h | 2 + widget/src/windows/nsWindow.cpp | 69 ++++++++++++++++++- widget/src/windows/nsWindow.h | 11 +++ widget/src/windows/nsWindowGfx.cpp | 44 ++++++++++-- 6 files changed, 124 insertions(+), 6 deletions(-) diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css index a549579a5009..40f18e6c31cf 100644 --- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -21,7 +21,7 @@ display: none; } - #main-window:not(:-moz-lwtheme) { + #main-window { -moz-appearance: -moz-win-borderless-glass; background: transparent; } diff --git a/widget/src/windows/nsUXThemeData.cpp b/widget/src/windows/nsUXThemeData.cpp index 4f39d4606749..126c6f37326c 100644 --- a/widget/src/windows/nsUXThemeData.cpp +++ b/widget/src/windows/nsUXThemeData.cpp @@ -93,6 +93,7 @@ nsUXThemeData::DwmExtendFrameIntoClientAreaProc nsUXThemeData::dwmExtendFrameInt nsUXThemeData::DwmIsCompositionEnabledProc nsUXThemeData::dwmIsCompositionEnabledPtr = NULL; nsUXThemeData::DwmSetIconicThumbnailProc nsUXThemeData::dwmSetIconicThumbnailPtr = NULL; nsUXThemeData::DwmSetIconicLivePreviewBitmapProc nsUXThemeData::dwmSetIconicLivePreviewBitmapPtr = NULL; +nsUXThemeData::DwmGetWindowAttributeProc nsUXThemeData::dwmGetWindowAttributePtr = NULL; nsUXThemeData::DwmSetWindowAttributeProc nsUXThemeData::dwmSetWindowAttributePtr = NULL; nsUXThemeData::DwmInvalidateIconicBitmapsProc nsUXThemeData::dwmInvalidateIconicBitmapsPtr = NULL; nsUXThemeData::DwmDefWindowProcProc nsUXThemeData::dwmDwmDefWindowProcPtr = NULL; @@ -141,6 +142,7 @@ nsUXThemeData::Initialize() dwmIsCompositionEnabledPtr = (DwmIsCompositionEnabledProc)::GetProcAddress(sDwmDLL, "DwmIsCompositionEnabled"); dwmSetIconicThumbnailPtr = (DwmSetIconicThumbnailProc)::GetProcAddress(sDwmDLL, "DwmSetIconicThumbnail"); dwmSetIconicLivePreviewBitmapPtr = (DwmSetIconicLivePreviewBitmapProc)::GetProcAddress(sDwmDLL, "DwmSetIconicLivePreviewBitmap"); + dwmGetWindowAttributePtr = (DwmGetWindowAttributeProc)::GetProcAddress(sDwmDLL, "DwmGetWindowAttribute"); dwmSetWindowAttributePtr = (DwmSetWindowAttributeProc)::GetProcAddress(sDwmDLL, "DwmSetWindowAttribute"); dwmInvalidateIconicBitmapsPtr = (DwmInvalidateIconicBitmapsProc)::GetProcAddress(sDwmDLL, "DwmInvalidateIconicBitmaps"); dwmDwmDefWindowProcPtr = (DwmDefWindowProcProc)::GetProcAddress(sDwmDLL, "DwmDefWindowProc"); diff --git a/widget/src/windows/nsUXThemeData.h b/widget/src/windows/nsUXThemeData.h index 9f422e796c19..ae81115d90c5 100644 --- a/widget/src/windows/nsUXThemeData.h +++ b/widget/src/windows/nsUXThemeData.h @@ -193,6 +193,7 @@ public: typedef HRESULT (WINAPI*DwmIsCompositionEnabledProc)(BOOL *pfEnabled); typedef HRESULT (WINAPI*DwmSetIconicThumbnailProc)(HWND hWnd, HBITMAP hBitmap, DWORD dwSITFlags); typedef HRESULT (WINAPI*DwmSetIconicLivePreviewBitmapProc)(HWND hWnd, HBITMAP hBitmap, POINT *pptClient, DWORD dwSITFlags); + typedef HRESULT (WINAPI*DwmGetWindowAttributeProc)(HWND hWnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); typedef HRESULT (WINAPI*DwmSetWindowAttributeProc)(HWND hWnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); typedef HRESULT (WINAPI*DwmInvalidateIconicBitmapsProc)(HWND hWnd); typedef HRESULT (WINAPI*DwmDefWindowProcProc)(HWND hWnd, UINT msg, LPARAM lParam, WPARAM wParam, LRESULT *aRetValue); @@ -201,6 +202,7 @@ public: static DwmIsCompositionEnabledProc dwmIsCompositionEnabledPtr; static DwmSetIconicThumbnailProc dwmSetIconicThumbnailPtr; static DwmSetIconicLivePreviewBitmapProc dwmSetIconicLivePreviewBitmapPtr; + static DwmGetWindowAttributeProc dwmGetWindowAttributePtr; static DwmSetWindowAttributeProc dwmSetWindowAttributePtr; static DwmInvalidateIconicBitmapsProc dwmInvalidateIconicBitmapsPtr; static DwmDefWindowProcProc dwmDwmDefWindowProcPtr; diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 53e7bfa495ab..79f240000d9b 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -2501,8 +2501,11 @@ void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, nsIntRect largest = opaqueRegion.GetLargestRectangle(); margins.cxLeftWidth = largest.x; margins.cxRightWidth = clientBounds.width - largest.XMost(); - margins.cyTopHeight = largest.y; margins.cyBottomHeight = clientBounds.height - largest.YMost(); + + // The minimum glass height must be the caption buttons height, + // otherwise the buttons are drawn incorrectly. + margins.cyTopHeight = PR_MAX(largest.y, mCaptionButtons.height); } // Only update glass area if there are changes @@ -2549,6 +2552,65 @@ void nsWindow::UpdateGlass() } #endif +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN +void nsWindow::UpdateCaptionButtonsClippingRect() +{ + NS_ASSERTION(mWnd, "UpdateCaptionButtonsClippingRect called with invalid mWnd."); + + RECT captionButtons; + mCaptionButtonsRoundedRegion.SetEmpty(); + mCaptionButtons.Empty(); + + if (!mCustomNonClient || + mSizeMode == nsSizeMode_Fullscreen || + mSizeMode == nsSizeMode_Minimized || + !nsUXThemeData::CheckForCompositor() || + FAILED(nsUXThemeData::dwmGetWindowAttributePtr(mWnd, + DWMWA_CAPTION_BUTTON_BOUNDS, + &captionButtons, + sizeof(captionButtons)))) { + return; + } + + mCaptionButtons = nsWindowGfx::ToIntRect(captionButtons); + + // Adjustments to reported area + PRInt32 leftMargin = (mNonClientMargins.left == -1) ? mHorResizeMargin : mNonClientMargins.left; + + // "leftMargin - 1" represents the resizer border and an + // one pixel adjustment to hide the semi-transparent highlight. + // The extra width is already excluded when the window is maximized. + mCaptionButtons.x -= leftMargin - 1; + + if (mSizeMode != nsSizeMode_Maximized) { + mCaptionButtons.width += leftMargin - 1; + mCaptionButtons.height -= mVertResizeMargin + 1; + } else { + // Adjustments to the buttons' shift from the edge of the screen, + // plus some apparently transparent drop shadow below them. + mCaptionButtons.width -= 2; + mCaptionButtons.height -= 3; + } + + // Create a rounded region by shrinking the 2 bottommost pixel rows from + // the rect by 1 and 2 pixels. + // mCaptionButtons: mCaptionButtonsRoundedRegion: + // +-----------+ +-----------+ + // | | | | + // | | | | + // +-----------+ +-------+ + nsIntRect round1(mCaptionButtons.x, mCaptionButtons.y, + mCaptionButtons.width, mCaptionButtons.height - 2); + nsIntRect round2(mCaptionButtons.x + 1, mCaptionButtons.YMost() - 2, + mCaptionButtons.width - 2, 1); + nsIntRect round3(mCaptionButtons.x + 2, mCaptionButtons.YMost() - 1, + mCaptionButtons.width - 4, 1); + mCaptionButtonsRoundedRegion.Or(mCaptionButtonsRoundedRegion, round1); + mCaptionButtonsRoundedRegion.Or(mCaptionButtonsRoundedRegion, round2); + mCaptionButtonsRoundedRegion.Or(mCaptionButtonsRoundedRegion, round3); +} +#endif + /************************************************************** * * SECTION: nsIWidget::HideWindowChrome @@ -6991,6 +7053,11 @@ PRBool nsWindow::OnResize(nsIntRect &aWindowRect) Invalidate(PR_FALSE); } #endif + +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + UpdateCaptionButtonsClippingRect(); +#endif + // call the event callback if (mEventCallback) { nsSizeEvent event(PR_TRUE, NS_SIZE, this); diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 4b74aeb49334..2d7f9919934b 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -454,6 +454,9 @@ protected: static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc); #endif // ACCESSIBILITY void ClearCachedResources(); +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + void UpdateCaptionButtonsClippingRect(); +#endif protected: nsCOMPtr mParent; @@ -505,6 +508,14 @@ protected: nsIntMargin mNonClientOffset; // Margins set by the owner nsIntMargin mNonClientMargins; + +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + // Represents the area taken by the caption buttons + // on dwm-enabled systems + nsIntRect mCaptionButtons; + nsIntRegion mCaptionButtonsRoundedRegion; +#endif + // Indicates custom frames are enabled PRPackedBool mCustomNonClient; // Cached copy of L&F's resize border diff --git a/widget/src/windows/nsWindowGfx.cpp b/widget/src/windows/nsWindowGfx.cpp index afb2ca36a414..db3d527f7563 100644 --- a/widget/src/windows/nsWindowGfx.cpp +++ b/widget/src/windows/nsWindowGfx.cpp @@ -246,11 +246,15 @@ void nsWindowGfx::OnSettingsChangeGfx(WPARAM wParam) nsIntRegion nsWindow::GetRegionToPaint(PRBool aForceFullRepaint, PAINTSTRUCT ps, HDC aDC) -{ +{ if (aForceFullRepaint) { RECT paintRect; ::GetClientRect(mWnd, &paintRect); - return nsIntRegion(nsWindowGfx::ToIntRect(paintRect)); + nsIntRegion region(nsWindowGfx::ToIntRect(paintRect)); +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + region.Sub(region, mCaptionButtonsRoundedRegion); +#endif + return region; } #if defined(WINCE_WINDOWS_MOBILE) || !defined(WINCE) @@ -270,11 +274,21 @@ nsIntRegion nsWindow::GetRegionToPaint(PRBool aForceFullRepaint, ::DeleteObject(paintRgn); # ifdef WINCE if (!rgn.IsEmpty()) -# endif return rgn; +# elif MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + rgn.Sub(rgn, mCaptionButtonsRoundedRegion); + return rgn; +# else + return rgn; +# endif } #endif - return nsIntRegion(nsWindowGfx::ToIntRect(ps.rcPaint)); + + nsIntRegion region(nsWindowGfx::ToIntRect(ps.rcPaint)); +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + region.Sub(region, mCaptionButtonsRoundedRegion); +#endif + return region; } #define WORDSSIZE(x) ((x).width * (x).height) @@ -561,6 +575,28 @@ DDRAW_FAILED: #endif } +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && + mTransparencyMode != eTransparencyTransparent && + !mCaptionButtons.IsEmpty()) { + // The area behind the caption buttons need to have a + // black background first to make the clipping work. + RECT rect; + rect.top = mCaptionButtons.y; + rect.left = mCaptionButtons.x; + rect.right = mCaptionButtons.x + mCaptionButtons.width; + rect.bottom = mCaptionButtons.y + mCaptionButtons.height; + FillRect(hDC, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); + + const nsIntRect* r; + for (nsIntRegionRectIterator iter(event.region); + (r = iter.Next()) != nsnull;) { + thebesContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), PR_TRUE); + } + thebesContext->Clip(); + } +#endif + { AutoLayerManagerSetup setupLayerManager(this, thebesContext, doubleBuffering);