summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-27 00:18:19 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-27 00:18:19 +0000
commit08c761bbfc715127e0102e5c7e25321cdaecc572 (patch)
tree01503d7b2f7f30b61bddbce05e5f531582c6496a /views
parentf9b522727619a692447c4575e03e17dab3550ae2 (diff)
downloadchromium_src-08c761bbfc715127e0102e5c7e25321cdaecc572.zip
chromium_src-08c761bbfc715127e0102e5c7e25321cdaecc572.tar.gz
chromium_src-08c761bbfc715127e0102e5c7e25321cdaecc572.tar.bz2
Fix various layered window updating bugs.
As it turns out, you can NOT rely on Windows to track the invalid rect for layered windows. This is likely because Windows doesn't believe them to have an invalid rect - it is up to the app to handle updating them. So, sadly, this means adding an invalid_rect_ field to WidgetWin and using it to track the invalid rect instead of InvalidateRect() - but only for WS_EX_LAYERED. I also split the layered window updating code out of RedrawInvalidRect for readability. http://crbug.com/74300 http://crbug.com/74301 TEST=see bugs TBR=sky Review URL: http://codereview.chromium.org/6591027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76172 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/widget/widget_win.cc75
-rw-r--r--views/widget/widget_win.h11
2 files changed, 52 insertions, 34 deletions
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index d1447de..8cde70f 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -527,9 +527,15 @@ View* WidgetWin::GetDraggedView() {
}
void WidgetWin::SchedulePaintInRect(const gfx::Rect& rect) {
- // InvalidateRect() expects client coordinates.
- RECT r = rect.ToRECT();
- InvalidateRect(hwnd(), &r, FALSE);
+ if (use_layered_buffer_) {
+ // We must update the back-buffer immediately, since Windows' handling of
+ // invalid rects is somewhat mysterious.
+ layered_window_invalid_rect_ = layered_window_invalid_rect_.Union(rect);
+ } else {
+ // InvalidateRect() expects client coordinates.
+ RECT r = rect.ToRECT();
+ InvalidateRect(hwnd(), &r, FALSE);
+ }
}
void WidgetWin::SetCursor(gfx::NativeCursor cursor) {
@@ -997,12 +1003,6 @@ void WidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
}
void WidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) {
- // Layered windows need to be explicitly invalidated, but any calls to
- // SchedulePaint() prior to the window being shown are ignored by Windows, so
- // we must manually invalidate the widget when it is shown. Non-layered
- // windows are automatically invalidated by Windows when they are shown.
- if (use_layered_buffer_ && window_pos->flags & SWP_SHOWWINDOW)
- InvalidateRect(hwnd(), NULL, FALSE);
SetMsgHandled(FALSE);
}
@@ -1175,9 +1175,9 @@ Window* WidgetWin::GetWindowImpl(HWND hwnd) {
}
void WidgetWin::SizeContents(const gfx::Size& window_size) {
- contents_.reset(new gfx::CanvasSkia(window_size.width(),
- window_size.height(),
- false));
+ layered_window_contents_.reset(new gfx::CanvasSkia(window_size.width(),
+ window_size.height(),
+ false));
}
RootView* WidgetWin::GetFocusedViewRootView() {
@@ -1234,33 +1234,42 @@ void WidgetWin::MakeMSG(MSG* msg, UINT message, WPARAM w_param, LPARAM l_param,
}
void WidgetWin::RedrawInvalidRect() {
- RECT r = { 0, 0, 0, 0 };
- if (GetUpdateRect(hwnd(), &r, FALSE) && !IsRectEmpty(&r)) {
- if (use_layered_buffer_) {
- // We need to clip to the dirty rect ourselves.
- contents_->save(SkCanvas::kClip_SaveFlag);
- contents_->ClipRectInt(r.left, r.top, r.right - r.left,
- r.bottom - r.top);
- GetRootView()->Paint(contents_.get());
- contents_->restore();
-
- RECT wr;
- GetWindowRect(&wr);
- SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
- POINT position = {wr.left, wr.top};
- HDC dib_dc = contents_->getTopPlatformDevice().getBitmapDC();
- POINT zero = {0, 0};
- BLENDFUNCTION blend = {AC_SRC_OVER, 0, layered_alpha_, AC_SRC_ALPHA};
- UpdateLayeredWindow(hwnd(), NULL, &position, &size, dib_dc, &zero,
- RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
- ValidateRect(hwnd(), &r);
- } else {
+ if (use_layered_buffer_) {
+ RedrawLayeredWindowContents();
+ } else {
+ RECT r = { 0, 0, 0, 0 };
+ if (GetUpdateRect(hwnd(), &r, FALSE) && !IsRectEmpty(&r)) {
RedrawWindow(hwnd(), &r, NULL,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
}
}
}
+void WidgetWin::RedrawLayeredWindowContents() {
+ if (layered_window_invalid_rect_.IsEmpty())
+ return;
+
+ // We need to clip to the dirty rect ourselves.
+ layered_window_contents_->save(SkCanvas::kClip_SaveFlag);
+ layered_window_contents_->ClipRectInt(layered_window_invalid_rect_.x(),
+ layered_window_invalid_rect_.y(),
+ layered_window_invalid_rect_.width(),
+ layered_window_invalid_rect_.height());
+ GetRootView()->Paint(layered_window_contents_.get());
+ layered_window_contents_->restore();
+
+ RECT wr;
+ GetWindowRect(&wr);
+ SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
+ POINT position = {wr.left, wr.top};
+ HDC dib_dc = layered_window_contents_->getTopPlatformDevice().getBitmapDC();
+ POINT zero = {0, 0};
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0, layered_alpha_, AC_SRC_ALPHA};
+ UpdateLayeredWindow(hwnd(), NULL, &position, &size, dib_dc, &zero,
+ RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
+ layered_window_invalid_rect_.SetRect(0, 0, 0, 0);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, public:
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index 820c4a7..6130ad1 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -502,6 +502,10 @@ class WidgetWin : public ui::WindowImpl,
// Synchronously paints the invalid contents of the Widget.
void RedrawInvalidRect();
+ // Synchronously updates the invalid contents of the Widget. Valid for
+ // layered windows only.
+ void RedrawLayeredWindowContents();
+
// A delegate implementation that handles events received here.
internal::NativeWidgetDelegate* delegate_;
@@ -531,7 +535,12 @@ class WidgetWin : public ui::WindowImpl,
// A canvas that contains the window contents in the case of a layered
// window.
- scoped_ptr<gfx::CanvasSkia> contents_;
+ scoped_ptr<gfx::CanvasSkia> layered_window_contents_;
+
+ // We must track the invalid rect for a layered window ourselves, since
+ // Windows will not do this properly with InvalidateRect()/GetUpdateRect().
+ // (In fact, it'll return misleading information from GetUpdateRect()).
+ gfx::Rect layered_window_invalid_rect_;
// Whether or not the window should delete itself when it is destroyed.
// Set this to false via its setter for stack allocated instances.