| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" | 5 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" |
| 6 | 6 |
| 7 #include "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
| 8 #include "app/gfx/gdi_util.h" | 8 #include "app/gfx/gdi_util.h" |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "app/l10n_util_win.h" | 10 #include "app/l10n_util_win.h" |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 lparam = rect->width() << 16 | rect->height(); | 561 lparam = rect->width() << 16 | rect->height(); |
| 562 | 562 |
| 563 // SendMessage gets the message across much quicker than PostMessage, since it | 563 // SendMessage gets the message across much quicker than PostMessage, since it |
| 564 // doesn't get queued. When the plugin thread calls PeekMessage or other | 564 // doesn't get queued. When the plugin thread calls PeekMessage or other |
| 565 // Win32 APIs, sent messages are dispatched automatically. | 565 // Win32 APIs, sent messages are dispatched automatically. |
| 566 SendNotifyMessage(hwnd, msg, wparam, lparam); | 566 SendNotifyMessage(hwnd, msg, wparam, lparam); |
| 567 | 567 |
| 568 return TRUE; | 568 return TRUE; |
| 569 } | 569 } |
| 570 | 570 |
| 571 void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) { | 571 void RenderWidgetHostViewWin::Redraw() { |
| 572 RECT damage_bounds; |
| 573 GetUpdateRect(&damage_bounds, FALSE); |
| 574 |
| 575 ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0)); |
| 576 GetUpdateRgn(damage_region, FALSE); |
| 577 |
| 572 // Paint the invalid region synchronously. Our caller will not paint again | 578 // Paint the invalid region synchronously. Our caller will not paint again |
| 573 // until we return, so by painting to the screen here, we ensure effective | 579 // until we return, so by painting to the screen here, we ensure effective |
| 574 // rate-limiting of backing store updates. This helps a lot on pages that | 580 // rate-limiting of backing store updates. This helps a lot on pages that |
| 575 // have animations or fairly expensive layout (e.g., google maps). | 581 // have animations or fairly expensive layout (e.g., google maps). |
| 576 // | 582 // |
| 577 // We paint this window synchronously, however child windows (i.e. plugins) | 583 // We paint this window synchronously, however child windows (i.e. plugins) |
| 578 // are painted asynchronously. By avoiding synchronous cross-process window | 584 // are painted asynchronously. By avoiding synchronous cross-process window |
| 579 // message dispatching we allow scrolling to be smooth, and also avoid the | 585 // message dispatching we allow scrolling to be smooth, and also avoid the |
| 580 // browser process locking up if the plugin process is hung. | 586 // browser process locking up if the plugin process is hung. |
| 581 // | 587 // |
| 582 RedrawWindow( | 588 RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN); |
| 583 &rect.ToRECT(), NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); | |
| 584 | 589 |
| 585 // Send the invalid rect in screen coordinates. | 590 // Send the invalid rect in screen coordinates. |
| 586 gfx::Rect screen_rect = GetViewBounds(); | 591 gfx::Rect screen_rect = GetViewBounds(); |
| 587 gfx::Rect invalid_screen_rect = rect; | 592 gfx::Rect invalid_screen_rect(damage_bounds); |
| 588 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); | 593 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); |
| 589 | 594 |
| 590 LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect); | 595 LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect); |
| 591 EnumChildWindows(m_hWnd, EnumChildProc, lparam); | 596 EnumChildWindows(m_hWnd, EnumChildProc, lparam); |
| 592 } | 597 } |
| 593 | 598 |
| 594 void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect, | 599 void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect, |
| 595 HDC dc) { | 600 HDC dc) { |
| 596 gfx::Rect resize_corner_rect = | 601 gfx::Rect resize_corner_rect = |
| 597 render_widget_host_->GetRootWindowResizerRect(); | 602 render_widget_host_->GetRootWindowResizerRect(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 612 } | 617 } |
| 613 canvas.DrawBitmapInt(*bitmap, 0, 0); | 618 canvas.DrawBitmapInt(*bitmap, 0, 0); |
| 614 canvas.getTopPlatformDevice().drawToHDC(dc, x, | 619 canvas.getTopPlatformDevice().drawToHDC(dc, x, |
| 615 resize_corner_rect.y() + resize_corner_rect.height() - | 620 resize_corner_rect.y() + resize_corner_rect.height() - |
| 616 bitmap->height(), NULL); | 621 bitmap->height(), NULL); |
| 617 if (rtl_dir) | 622 if (rtl_dir) |
| 618 canvas.restore(); | 623 canvas.restore(); |
| 619 } | 624 } |
| 620 } | 625 } |
| 621 | 626 |
| 622 void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) { | 627 void RenderWidgetHostViewWin::DidPaintBackingStoreRects( |
| 628 const std::vector<gfx::Rect>& rects) { |
| 623 if (is_hidden_) | 629 if (is_hidden_) |
| 624 return; | 630 return; |
| 625 | 631 |
| 626 if (about_to_validate_and_paint_) | 632 for (size_t i = 0; i < rects.size(); ++i) |
| 627 InvalidateRect(&rect.ToRECT(), false); | 633 InvalidateRect(&rects[i].ToRECT(), false); |
| 628 else | 634 |
| 629 Redraw(rect); | 635 if (!about_to_validate_and_paint_) |
| 636 Redraw(); |
| 630 } | 637 } |
| 631 | 638 |
| 632 void RenderWidgetHostViewWin::DidScrollRect( | 639 void RenderWidgetHostViewWin::DidScrollBackingStoreRect( |
| 633 const gfx::Rect& rect, int dx, int dy) { | 640 const gfx::Rect& rect, int dx, int dy) { |
| 634 if (is_hidden_) | 641 if (is_hidden_) |
| 635 return; | 642 return; |
| 636 | 643 |
| 637 // We need to pass in SW_INVALIDATE to ScrollWindowEx. The MSDN | 644 // We need to pass in SW_INVALIDATE to ScrollWindowEx. The documentation on |
| 638 // documentation states that it only applies to the HRGN argument, which is | 645 // MSDN states that it only applies to the HRGN argument, which is wrong. |
| 639 // wrong. Not passing in this flag does not invalidate the region which was | 646 // Not passing in this flag does not invalidate the region which was scrolled |
| 640 // scrolled from, thus causing painting issues. | 647 // from, thus causing painting issues. |
| 641 RECT clip_rect = rect.ToRECT(); | 648 RECT clip_rect = rect.ToRECT(); |
| 642 ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE); | 649 ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE); |
| 643 | |
| 644 RECT invalid_rect = {0}; | |
| 645 GetUpdateRect(&invalid_rect); | |
| 646 Redraw(gfx::Rect(invalid_rect)); | |
| 647 } | 650 } |
| 648 | 651 |
| 649 void RenderWidgetHostViewWin::RenderViewGone() { | 652 void RenderWidgetHostViewWin::RenderViewGone() { |
| 650 // TODO(darin): keep this around, and draw sad-tab into it. | 653 // TODO(darin): keep this around, and draw sad-tab into it. |
| 651 UpdateCursorIfOverSelf(); | 654 UpdateCursorIfOverSelf(); |
| 652 being_destroyed_ = true; | 655 being_destroyed_ = true; |
| 653 DestroyWindow(); | 656 DestroyWindow(); |
| 654 } | 657 } |
| 655 | 658 |
| 656 void RenderWidgetHostViewWin::WillDestroyRenderWidget(RenderWidgetHost* rwh) { | 659 void RenderWidgetHostViewWin::WillDestroyRenderWidget(RenderWidgetHost* rwh) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 void RenderWidgetHostViewWin::OnPaint(HDC dc) { | 761 void RenderWidgetHostViewWin::OnPaint(HDC dc) { |
| 759 DCHECK(render_widget_host_->process()->HasConnection()); | 762 DCHECK(render_widget_host_->process()->HasConnection()); |
| 760 | 763 |
| 761 about_to_validate_and_paint_ = true; | 764 about_to_validate_and_paint_ = true; |
| 762 BackingStore* backing_store = render_widget_host_->GetBackingStore(true); | 765 BackingStore* backing_store = render_widget_host_->GetBackingStore(true); |
| 763 | 766 |
| 764 // We initialize |paint_dc| (and thus call BeginPaint()) after calling | 767 // We initialize |paint_dc| (and thus call BeginPaint()) after calling |
| 765 // GetBackingStore(), so that if it updates the invalid rect we'll catch the | 768 // GetBackingStore(), so that if it updates the invalid rect we'll catch the |
| 766 // changes and repaint them. | 769 // changes and repaint them. |
| 767 about_to_validate_and_paint_ = false; | 770 about_to_validate_and_paint_ = false; |
| 771 |
| 772 // Grab the region to paint before creation of paint_dc since it clears the |
| 773 // damage region. |
| 774 ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0)); |
| 775 GetUpdateRgn(damage_region, FALSE); |
| 776 |
| 768 CPaintDC paint_dc(m_hWnd); | 777 CPaintDC paint_dc(m_hWnd); |
| 769 | 778 |
| 770 gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); | 779 gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); |
| 771 if (damaged_rect.IsEmpty()) | 780 if (damaged_rect.IsEmpty()) |
| 772 return; | 781 return; |
| 773 | 782 |
| 774 if (backing_store) { | 783 if (backing_store) { |
| 775 gfx::Rect bitmap_rect( | 784 gfx::Rect bitmap_rect(gfx::Point(), backing_store->size()); |
| 776 0, 0, backing_store->size().width(), backing_store->size().height()); | |
| 777 | 785 |
| 778 gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect); | 786 bool manage_colors = BackingStore::ColorManagementEnabled(); |
| 779 if (!paint_rect.IsEmpty()) { | 787 if (manage_colors) |
| 780 DrawResizeCorner(paint_rect, backing_store->hdc()); | 788 SetICMMode(paint_dc.m_hDC, ICM_ON); |
| 781 bool manage_colors = BackingStore::ColorManagementEnabled(); | 789 |
| 782 if (manage_colors) | 790 // Blit only the damaged regions from the backing store. |
| 783 SetICMMode(paint_dc.m_hDC, ICM_ON); | 791 DWORD data_size = GetRegionData(damage_region, 0, NULL); |
| 784 BitBlt(paint_dc.m_hDC, | 792 scoped_array<char> region_data_buf(new char[data_size]); |
| 785 paint_rect.x(), | 793 RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get()); |
| 786 paint_rect.y(), | 794 GetRegionData(damage_region, data_size, region_data); |
| 787 paint_rect.width(), | 795 |
| 788 paint_rect.height(), | 796 RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer); |
| 789 backing_store->hdc(), | 797 for (DWORD i = 0; i < region_data->rdh.nCount; ++i) { |
| 790 paint_rect.x(), | 798 gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i])); |
| 791 paint_rect.y(), | 799 if (!paint_rect.IsEmpty()) { |
| 792 SRCCOPY); | 800 DrawResizeCorner(paint_rect, backing_store->hdc()); |
| 793 if (manage_colors) | 801 BitBlt(paint_dc.m_hDC, |
| 794 SetICMMode(paint_dc.m_hDC, ICM_OFF); | 802 paint_rect.x(), |
| 803 paint_rect.y(), |
| 804 paint_rect.width(), |
| 805 paint_rect.height(), |
| 806 backing_store->hdc(), |
| 807 paint_rect.x(), |
| 808 paint_rect.y(), |
| 809 SRCCOPY); |
| 810 } |
| 795 } | 811 } |
| 796 | 812 |
| 813 if (manage_colors) |
| 814 SetICMMode(paint_dc.m_hDC, ICM_OFF); |
| 815 |
| 797 // Fill the remaining portion of the damaged_rect with the background | 816 // Fill the remaining portion of the damaged_rect with the background |
| 798 if (damaged_rect.right() > bitmap_rect.right()) { | 817 if (damaged_rect.right() > bitmap_rect.right()) { |
| 799 RECT r; | 818 RECT r; |
| 800 r.left = std::max(bitmap_rect.right(), damaged_rect.x()); | 819 r.left = std::max(bitmap_rect.right(), damaged_rect.x()); |
| 801 r.right = damaged_rect.right(); | 820 r.right = damaged_rect.right(); |
| 802 r.top = damaged_rect.y(); | 821 r.top = damaged_rect.y(); |
| 803 r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom()); | 822 r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom()); |
| 804 DrawBackground(r, &paint_dc); | 823 DrawBackground(r, &paint_dc); |
| 805 } | 824 } |
| 806 if (damaged_rect.bottom() > bitmap_rect.bottom()) { | 825 if (damaged_rect.bottom() > bitmap_rect.bottom()) { |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 SetFocus(); | 1481 SetFocus(); |
| 1463 } | 1482 } |
| 1464 } | 1483 } |
| 1465 | 1484 |
| 1466 void RenderWidgetHostViewWin::ShutdownHost() { | 1485 void RenderWidgetHostViewWin::ShutdownHost() { |
| 1467 shutdown_factory_.RevokeAll(); | 1486 shutdown_factory_.RevokeAll(); |
| 1468 if (render_widget_host_) | 1487 if (render_widget_host_) |
| 1469 render_widget_host_->Shutdown(); | 1488 render_widget_host_->Shutdown(); |
| 1470 // Do not touch any members at this point, |this| has been deleted. | 1489 // Do not touch any members at this point, |this| has been deleted. |
| 1471 } | 1490 } |
| OLD | NEW |