diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 17:02:25 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 17:02:25 +0000 |
commit | f05c3e12f1fafedb16a5dcfc0b4ec1a4c2c019a1 (patch) | |
tree | 0e9f7ebd92381f9c67baa740c7ba472c8a5f64a1 /views/window | |
parent | 0dedf72573b37d924b4a29b76cb17550d2cf5f81 (diff) | |
download | chromium_src-f05c3e12f1fafedb16a5dcfc0b4ec1a4c2c019a1.zip chromium_src-f05c3e12f1fafedb16a5dcfc0b4ec1a4c2c019a1.tar.gz chromium_src-f05c3e12f1fafedb16a5dcfc0b4ec1a4c2c019a1.tar.bz2 |
Fix some rendering glitches in the custom frame by re-introducing nasty old code since I have found no way to avoid using it.
BUG=79640
TEST=see bug
Review URL: http://codereview.chromium.org/7038021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85774 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/window')
-rw-r--r-- | views/window/window_win.cc | 122 | ||||
-rw-r--r-- | views/window/window_win.h | 3 |
2 files changed, 108 insertions, 17 deletions
diff --git a/views/window/window_win.cc b/views/window/window_win.cc index 2845379..f50cefa 100644 --- a/views/window/window_win.cc +++ b/views/window/window_win.cc @@ -246,8 +246,7 @@ WindowWin::WindowWin(internal::NativeWindowDelegate* delegate) ignore_pos_changes_factory_(this), force_hidden_count_(0), is_right_mouse_pressed_on_caption_(false), - last_monitor_(NULL), - is_in_size_move_(false) { + last_monitor_(NULL) { is_window_ = true; // Initialize these values to 0 so that subclasses can override the default // behavior before calling Init. @@ -404,23 +403,13 @@ LRESULT WindowWin::OnDwmCompositionChanged(UINT msg, WPARAM w_param, } void WindowWin::OnEnterSizeMove() { - is_in_size_move_ = true; WidgetWin::OnEnterSizeMove(); delegate_->OnNativeWindowBeginUserBoundsChange(); } void WindowWin::OnExitSizeMove() { - is_in_size_move_ = false; WidgetWin::OnExitSizeMove(); delegate_->OnNativeWindowEndUserBoundsChange(); - - if (!GetWindow()->ShouldUseNativeFrame()) { - // Sending SWP_FRAMECHANGED forces a non-client repaint, which fixes the - // glitch in rendering the bottom pixel of the window caused by us - // offsetting the client rect there (See comment in GetClientAreaInsets()). - SetWindowPos(NULL, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); - } } void WindowWin::OnFinalMessage(HWND window) { @@ -687,11 +676,116 @@ LRESULT WindowWin::OnNCHitTest(const CPoint& point) { return WidgetWin::OnNCHitTest(point); } +namespace { +struct ClipState { + // The window being painted. + HWND parent; + + // DC painting to. + HDC dc; + + // Origin of the window in terms of the screen. + int x; + int y; +}; + +// See comments in OnNCPaint for details of this function. +static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) { + ClipState* clip_state = reinterpret_cast<ClipState*>(param); + if (GetParent(window) == clip_state->parent && IsWindowVisible(window)) { + RECT bounds; + GetWindowRect(window, &bounds); + ExcludeClipRect(clip_state->dc, + bounds.left - clip_state->x, + bounds.top - clip_state->y, + bounds.right - clip_state->x, + bounds.bottom - clip_state->y); + } + return TRUE; +} +} // namespace + void WindowWin::OnNCPaint(HRGN rgn) { + // We only do non-client painting if we're not using the native frame. + // It's required to avoid some native painting artifacts from appearing when + // the window is resized. + if (GetWindow()->ShouldUseNativeFrame()) { + WidgetWin::OnNCPaint(rgn); + return; + } + + // We have an NC region and need to paint it. We expand the NC region to + // include the dirty region of the root view. This is done to minimize + // paints. + CRect window_rect; + GetWindowRect(&window_rect); + + if (window_rect.Width() != GetWidget()->GetRootView()->width() || + window_rect.Height() != GetWidget()->GetRootView()->height()) { + // If the size of the window differs from the size of the root view it + // means we're being asked to paint before we've gotten a WM_SIZE. This can + // happen when the user is interactively resizing the window. To avoid + // mass flickering we don't do anything here. Once we get the WM_SIZE we'll + // reset the region of the window which triggers another WM_NCPAINT and + // all is well. + return; + } + + CRect dirty_region; + // A value of 1 indicates paint all. + if (!rgn || rgn == reinterpret_cast<HRGN>(1)) { + dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height()); + } else { + RECT rgn_bounding_box; + GetRgnBox(rgn, &rgn_bounding_box); + if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect)) + return; // Dirty region doesn't intersect window bounds, bale. + + // rgn_bounding_box is in screen coordinates. Map it to window coordinates. + OffsetRect(&dirty_region, -window_rect.left, -window_rect.top); + } + + // In theory GetDCEx should do what we want, but I couldn't get it to work. + // In particular the docs mentiond DCX_CLIPCHILDREN, but as far as I can tell + // it doesn't work at all. So, instead we get the DC for the window then + // manually clip out the children. + HDC dc = GetWindowDC(GetNativeView()); + ClipState clip_state; + clip_state.x = window_rect.left; + clip_state.y = window_rect.top; + clip_state.parent = GetNativeView(); + clip_state.dc = dc; + EnumChildWindows(GetNativeView(), &ClipDCToChild, + reinterpret_cast<LPARAM>(&clip_state)); + + RootView* root_view = GetWidget()->GetRootView(); + gfx::Rect old_paint_region = invalid_rect(); + + if (!old_paint_region.IsEmpty()) { + // The root view has a region that needs to be painted. Include it in the + // region we're going to paint. + + CRect old_paint_region_crect = old_paint_region.ToRECT(); + CRect tmp = dirty_region; + UnionRect(&dirty_region, &tmp, &old_paint_region_crect); + } + + GetWidget()->GetRootView()->SchedulePaintInRect(gfx::Rect(dirty_region)); + + // gfx::CanvasSkiaPaint's destructor does the actual painting. As such, wrap + // the following in a block to force paint to occur so that we can release + // the dc. + { + gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left, + dirty_region.top, dirty_region.Width(), + dirty_region.Height()); + delegate_->AsNativeWidgetDelegate()->OnNativeWidgetPaint(&canvas); + } + + ReleaseDC(GetNativeView(), dc); // When using a custom frame, we want to avoid calling DefWindowProc() since // that may render artifacts. - SetMsgHandled((!IsActive() || is_in_size_move_) && - !GetWindow()->ShouldUseNativeFrame()); + SetMsgHandled(!GetWindow()->ShouldUseNativeFrame()); } LRESULT WindowWin::OnNCUAHDrawCaption(UINT msg, WPARAM w_param, diff --git a/views/window/window_win.h b/views/window/window_win.h index 5270034..c829e13 100644 --- a/views/window/window_win.h +++ b/views/window/window_win.h @@ -268,9 +268,6 @@ class WindowWin : public WidgetWin, DWORD drag_frame_saved_window_style_; DWORD drag_frame_saved_window_ex_style_; - // True when the window is being moved/sized. - bool is_in_size_move_; - DISALLOW_COPY_AND_ASSIGN(WindowWin); }; |