diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index d98db26b40b2..3a557ea99c21 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -2108,6 +2108,63 @@ nsWindow::SetNonClientMargins(nsIntMargin &margins) return NS_OK; } +void +nsWindow::InvalidateNonClientRegion() +{ + // +-+-----------------------+-+ + // | | app non-client chrome | | + // | +-----------------------+ | + // | | app client chrome | | } + // | +-----------------------+ | } + // | | app content | | } area we don't want to invalidate + // | +-----------------------+ | } + // | | app client chrome | | } + // | +-----------------------+ | + // +---------------------------+ < + // ^ ^ windows non-client chrome + // client area = app * + RECT rect; + GetWindowRect(mWnd, &rect); + MapWindowPoints(NULL, mWnd, (LPPOINT)&rect, 2); + HRGN winRgn = CreateRectRgnIndirect(&rect); + + // Subtract app client chrome and app content leaving + // windows non-client chrome and app non-client chrome + // in winRgn. + GetWindowRect(mWnd, &rect); + rect.top += mCaptionHeight; + rect.right -= mHorResizeMargin; + rect.bottom -= mHorResizeMargin; + rect.left += mVertResizeMargin; + MapWindowPoints(NULL, mWnd, (LPPOINT)&rect, 2); + HRGN clientRgn = CreateRectRgnIndirect(&rect); + CombineRgn(winRgn, winRgn, clientRgn, RGN_DIFF); + DeleteObject(clientRgn); + + // triggers ncpaint and paint events for the two areas + RedrawWindow(mWnd, NULL, winRgn, RDW_FRAME|RDW_INVALIDATE); + DeleteObject(winRgn); +} + +HRGN +nsWindow::ExcludeNonClientFromPaintRegion(HRGN aRegion) +{ + RECT rect; + HRGN rgn = NULL; + if (aRegion == (HRGN)1) { // undocumented value indicating a full refresh + GetWindowRect(mWnd, &rect); + rgn = CreateRectRgnIndirect(&rect); + } else { + rgn = aRegion; + } + GetClientRect(mWnd, &rect); + MapWindowPoints(mWnd, NULL, (LPPOINT)&rect, 2); + HRGN nonClientRgn = CreateRectRgnIndirect(&rect); + CombineRgn(rgn, rgn, nonClientRgn, RGN_DIFF); + DeleteObject(nonClientRgn); + return rgn; +} + /************************************************************** * * SECTION: nsIWidget::SetBackgroundColor @@ -4705,6 +4762,87 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, break; } + case WM_SETTEXT: + /* + * WM_SETTEXT paints the titlebar area. Avoid this if we have a + * custom titlebar we paint ourselves. + */ + + if (mNonClientMargins.top == -1) + break; + + { + // From msdn, the way around this is to disable the visible state + // temporarily. We need the text to be set but we don't want the + // redraw to occur. + DWORD style = GetWindowLong(mWnd, GWL_STYLE); + SetWindowLong(mWnd, GWL_STYLE, style & ~WS_VISIBLE); + *aRetValue = CallWindowProcW(GetPrevWindowProc(), mWnd, + msg, wParam, lParam); + SetWindowLong(mWnd, GWL_STYLE, style); + return PR_TRUE; + } + + case WM_NCACTIVATE: + { + /* + * WM_NCACTIVATE paints nc areas. Avoid this and re-route painting + * through WM_NCPAINT via InvalidateNonClientRegion. + */ + + if (!mCustomNonClient) + break; + +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + // let the dwm handle nc painting on glass + if(nsUXThemeData::CheckForCompositor()) + break; +#endif + + if (wParam == TRUE) { + // going active + *aRetValue = FALSE; // ignored + result = PR_TRUE; + // invalidate to trigger a paint + InvalidateNonClientRegion(); + break; + } else { + // going inactive + *aRetValue = TRUE; // go ahead and deactive + result = PR_TRUE; + // invalidate to trigger a paint + InvalidateNonClientRegion(); + break; + } + } + + case WM_NCPAINT: + { + /* + * Reset the non-client paint region so that it excludes the + * non-client areas we paint manually. Then call defwndproc + * to do the actual painting. + */ + + if (!mCustomNonClient) + break; + +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + // let the dwm handle nc painting on glass + if(nsUXThemeData::CheckForCompositor()) + break; +#endif + + HRGN paintRgn = ExcludeNonClientFromPaintRegion((HRGN)wParam); + LRESULT res = CallWindowProcW(GetPrevWindowProc(), mWnd, + msg, (WPARAM)paintRgn, lParam); + if (paintRgn != (HRGN)wParam) + DeleteObject(paintRgn); + *aRetValue = res; + result = PR_TRUE; + } + break; + #ifndef WINCE case WM_POWERBROADCAST: // only hidden window handle this diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 9b4cd79dad32..0599b52d9f20 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -302,6 +302,8 @@ protected: PRBool CanTakeFocus(); PRBool UpdateNonClientMargins(PRInt32 aSizeMode = -1, PRBool aReflowWindow = PR_TRUE); void ResetLayout(); + void InvalidateNonClientRegion(); + HRGN ExcludeNonClientFromPaintRegion(HRGN aRegion); #if !defined(WINCE) static void InitTrackPointHack(); #endif