Chromium Code Reviews| 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.h" | 5 #include "chrome/browser/renderer_host/render_widget_host.h" |
| 6 | 6 |
| 7 #include "base/histogram.h" | 7 #include "base/histogram.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/keyboard_codes.h" | 9 #include "base/keyboard_codes.h" |
| 10 #include "chrome/browser/renderer_host/backing_store.h" | 10 #include "chrome/browser/renderer_host/backing_store.h" |
| 11 #include "chrome/browser/renderer_host/render_process_host.h" | 11 #include "chrome/browser/renderer_host/render_process_host.h" |
| 12 #include "chrome/browser/renderer_host/render_widget_helper.h" | 12 #include "chrome/browser/renderer_host/render_widget_helper.h" |
| 13 #include "chrome/browser/renderer_host/render_widget_host_view.h" | 13 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
| 14 #include "chrome/common/notification_service.h" | 14 #include "chrome/common/notification_service.h" |
| 15 #include "chrome/common/render_messages.h" | 15 #include "chrome/common/render_messages.h" |
| 16 #include "skia/ext/platform_canvas.h" | |
| 16 #include "views/view.h" | 17 #include "views/view.h" |
| 17 #include "webkit/glue/webcursor.h" | 18 #include "webkit/glue/webcursor.h" |
| 18 #include "webkit/glue/webtextdirection.h" | 19 #include "webkit/glue/webtextdirection.h" |
| 19 | 20 |
| 20 #if defined(OS_WIN) | 21 #if defined(OS_WIN) |
| 21 #include "base/gfx/gdi_util.h" | 22 #include "base/gfx/gdi_util.h" |
| 22 #include "chrome/app/chrome_dll_resource.h" | 23 #include "chrome/app/chrome_dll_resource.h" |
| 23 #endif // defined(OS_WIN) | 24 #endif // defined(OS_WIN) |
| 24 | 25 |
| 25 using base::Time; | 26 using base::Time; |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags); | 491 ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags); |
| 491 if (is_repaint_ack) { | 492 if (is_repaint_ack) { |
| 492 repaint_ack_pending_ = false; | 493 repaint_ack_pending_ = false; |
| 493 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; | 494 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; |
| 494 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); | 495 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); |
| 495 } | 496 } |
| 496 | 497 |
| 497 DCHECK(!params.bitmap_rect.IsEmpty()); | 498 DCHECK(!params.bitmap_rect.IsEmpty()); |
| 498 DCHECK(!params.view_size.IsEmpty()); | 499 DCHECK(!params.view_size.IsEmpty()); |
| 499 | 500 |
| 500 const size_t size = params.bitmap_rect.height() * | |
| 501 params.bitmap_rect.width() * 4; | |
| 502 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | 501 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); |
| 503 if (dib) { | 502 if (dib) { |
| 503 const size_t size = params.bitmap_rect.height() * | |
| 504 skia::PlatformCanvas::StrideForWidth(params.bitmap_rect.width()); | |
| 504 if (dib->size() < size) { | 505 if (dib->size() < size) { |
| 505 DLOG(WARNING) << "Transport DIB too small for given rectangle"; | 506 DLOG(WARNING) << "Transport DIB too small for given rectangle"; |
| 506 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); | 507 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); |
| 507 } else { | 508 } else { |
| 508 // Paint the backing store. This will update it with the renderer-supplied | 509 // Paint the backing store. This will update it with the |
| 509 // bits. The view will read out of the backing store later to actually | 510 // renderer-supplied bits. The view will read out of the backing |
| 510 // draw to the screen. | 511 // store later to actually draw to the screen. |
| 511 PaintBackingStoreRect(dib, params.bitmap_rect, params.view_size); | 512 PaintBackingStoreRects(dib, params.bitmap_rect, params.paint_rects, |
| 513 params.view_size); | |
| 512 } | 514 } |
| 513 } | 515 } |
| 514 | 516 |
| 515 // ACK early so we can prefetch the next PaintRect if there is a next one. | 517 // ACK early so we can prefetch the next PaintRect if there is a next one. |
| 516 // This must be done AFTER we're done painting with the bitmap supplied by the | 518 // This must be done AFTER we're done painting with the bitmap supplied by the |
| 517 // renderer. This ACK is a signal to the renderer that the backing store can | 519 // renderer. This ACK is a signal to the renderer that the backing store can |
| 518 // be re-used, so the bitmap may be invalid after this call. | 520 // be re-used, so the bitmap may be invalid after this call. |
| 519 Send(new ViewMsg_PaintRect_ACK(routing_id_)); | 521 Send(new ViewMsg_PaintRect_ACK(routing_id_)); |
| 520 | 522 |
| 521 // We don't need to update the view if the view is hidden. We must do this | 523 // We don't need to update the view if the view is hidden. We must do this |
| 522 // early return after the ACK is sent, however, or the renderer will not send | 524 // early return after the ACK is sent, however, or the renderer will not send |
| 523 // is more data. | 525 // is more data. |
| 524 if (is_hidden_) | 526 if (is_hidden_) |
| 525 return; | 527 return; |
| 526 | 528 |
| 527 // Now paint the view. Watch out: it might be destroyed already. | 529 // Now paint the view. Watch out: it might be destroyed already. |
| 528 if (view_) { | 530 if (view_) { |
| 529 view_->MovePluginWindows(params.plugin_window_moves); | 531 view_->MovePluginWindows(params.plugin_window_moves); |
| 530 view_being_painted_ = true; | 532 view_being_painted_ = true; |
| 531 view_->DidPaintRect(params.bitmap_rect); | 533 if (params.paint_rects.empty()) { |
| 534 view_->DidPaintRect(params.bitmap_rect); | |
| 535 } else { | |
| 536 for (size_t i = 0; i < params.paint_rects.size(); ++i) | |
| 537 view_->DidPaintRect(params.paint_rects[i]); | |
| 538 } | |
| 532 view_being_painted_ = false; | 539 view_being_painted_ = false; |
| 533 } | 540 } |
| 534 | 541 |
| 535 if (paint_observer_.get()) | 542 if (paint_observer_.get()) |
| 536 paint_observer_->RenderWidgetHostDidPaint(this); | 543 paint_observer_->RenderWidgetHostDidPaint(this); |
| 537 | 544 |
| 538 // If we got a resize ack, then perhaps we have another resize to send? | 545 // If we got a resize ack, then perhaps we have another resize to send? |
| 539 if (is_resize_ack && view_) { | 546 if (is_resize_ack && view_) { |
| 540 gfx::Rect view_bounds = view_->GetViewBounds(); | 547 gfx::Rect view_bounds = view_->GetViewBounds(); |
| 541 if (current_size_.width() != view_bounds.width() || | 548 if (current_size_.width() != view_bounds.width() || |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 612 mouse_move_pending_ = false; | 619 mouse_move_pending_ = false; |
| 613 | 620 |
| 614 // now, we can send the next mouse move event | 621 // now, we can send the next mouse move event |
| 615 if (next_mouse_move_.get()) { | 622 if (next_mouse_move_.get()) { |
| 616 DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove); | 623 DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove); |
| 617 ForwardMouseEvent(*next_mouse_move_); | 624 ForwardMouseEvent(*next_mouse_move_); |
| 618 } | 625 } |
| 619 } | 626 } |
| 620 | 627 |
| 621 if (WebInputEvent::isKeyboardEventType(type)) { | 628 if (WebInputEvent::isKeyboardEventType(type)) { |
| 622 if (key_queue_.size() == 0) { | 629 if (key_queue_.empty()) { |
| 623 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " | 630 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " |
| 624 << "don't seem to have sent it to the renderer!"; | 631 << "don't seem to have sent it to the renderer!"; |
| 625 } else if (key_queue_.front().type != type) { | 632 } else if (key_queue_.front().type != type) { |
| 626 LOG(ERROR) << "We seem to have a different key type sent from " | 633 LOG(ERROR) << "We seem to have a different key type sent from " |
| 627 << "the renderer. (" << key_queue_.front().type << " vs. " | 634 << "the renderer. (" << key_queue_.front().type << " vs. " |
| 628 << type << "). Ignoring event."; | 635 << type << "). Ignoring event."; |
| 629 } else { | 636 } else { |
| 630 bool processed = false; | 637 bool processed = false; |
| 631 r = message.ReadBool(&iter, &processed); | 638 r = message.ReadBool(&iter, &processed); |
| 632 DCHECK(r); | 639 DCHECK(r); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 | 687 |
| 681 view_->ShowPopupWithItems(validated_params.bounds, | 688 view_->ShowPopupWithItems(validated_params.bounds, |
| 682 validated_params.item_height, | 689 validated_params.item_height, |
| 683 validated_params.selected_item, | 690 validated_params.selected_item, |
| 684 validated_params.popup_items); | 691 validated_params.popup_items); |
| 685 #else // OS_WIN || OS_LINUX | 692 #else // OS_WIN || OS_LINUX |
| 686 NOTREACHED(); | 693 NOTREACHED(); |
| 687 #endif | 694 #endif |
| 688 } | 695 } |
| 689 | 696 |
| 690 void RenderWidgetHost::PaintBackingStoreRect(TransportDIB* bitmap, | 697 static bool CoversArea(const std::vector<gfx::Rect>& rects, |
|
darin (slow to review)
2009/06/10 17:23:24
nit: please move helper functions to the top of th
MAD
2009/06/10 19:00:13
Done.
| |
| 691 const gfx::Rect& bitmap_rect, | 698 const gfx::Size& size) { |
| 692 const gfx::Size& view_size) { | 699 #ifndef NDEBUG |
| 700 // Make sure there are no overlapping rects. That would make the | |
| 701 // test below irrelevant. We only do it in the debug build since | |
| 702 // this case "should" be covered in the renderer. | |
| 703 gfx::Rect view_rect(size.width(), size.height()); | |
| 704 size_t last_index = rects.size() - 1; | |
| 705 for (size_t i = 0; i < last_index; ++i) { | |
| 706 DCHECK(view_rect.Contains(rects[i])); | |
| 707 for (size_t j = i + 1; i < rects.size(); ++i) | |
| 708 DCHECK(!rects[i].Intersects(rects[j])); | |
| 709 } | |
| 710 DCHECK(view_rect.Contains(rects[last_index])); | |
| 711 #endif | |
| 712 int target_area = size.height() * size.width(); | |
| 713 int covered_area = 0; | |
| 714 for (size_t i = 0; i < rects.size(); ++i) { | |
| 715 covered_area += rects[i].height() * rects[i].width(); | |
| 716 } | |
| 717 return covered_area < target_area; | |
| 718 } | |
| 719 | |
| 720 void RenderWidgetHost::PaintBackingStoreRects( | |
| 721 TransportDIB* bitmap, const gfx::Rect& bitmap_rect, | |
| 722 const std::vector<gfx::Rect>& paint_rects, | |
| 723 const gfx::Size& view_size) { | |
| 693 // The view may be destroyed already. | 724 // The view may be destroyed already. |
| 694 if (!view_) | 725 if (!view_) |
| 695 return; | 726 return; |
| 696 | 727 |
| 697 if (is_hidden_) { | 728 if (is_hidden_) { |
| 698 // Don't bother updating the backing store when we're hidden. Just mark it | 729 // Don't bother updating the backing store when we're hidden. Just mark it |
| 699 // as being totally invalid. This will cause a complete repaint when the | 730 // as being totally invalid. This will cause a complete repaint when the |
| 700 // view is restored. | 731 // view is restored. |
| 701 needs_repainting_on_restore_ = true; | 732 needs_repainting_on_restore_ = true; |
| 702 return; | 733 return; |
| 703 } | 734 } |
| 704 | 735 |
| 705 bool needs_full_paint = false; | 736 bool needs_full_paint = false; |
| 706 BackingStore* backing_store = | 737 base::ProcessHandle process_handle = process_->process().handle(); |
| 707 BackingStoreManager::PrepareBackingStore(this, view_size, | 738 if (paint_rects.empty()) { |
| 708 process_->process().handle(), | 739 BackingStore* backing_store = |
| 709 bitmap, bitmap_rect, | 740 BackingStoreManager::PrepareBackingStore(this, view_size, |
| 710 &needs_full_paint); | 741 process_handle, bitmap, bitmap_rect, bitmap_rect, |
| 711 DCHECK(backing_store != NULL); | 742 &needs_full_paint); |
| 743 DCHECK(backing_store != NULL); | |
| 744 } else { | |
| 745 bool checked_coverage = false; | |
| 746 // TODO(agl): Reduce the number of X server round trips on Linux. | |
| 747 for (size_t i = 0; i < paint_rects.size(); ++i) { | |
| 748 BackingStore* backing_store = | |
| 749 BackingStoreManager::PrepareBackingStore(this, view_size, | |
| 750 process_handle, bitmap, bitmap_rect, paint_rects[i], | |
| 751 &needs_full_paint); | |
| 752 DCHECK(backing_store != NULL); | |
| 753 if (needs_full_paint) { | |
| 754 // We should not need a full paint more than once for a given view size | |
| 755 DCHECK(!checked_coverage); | |
| 756 checked_coverage = true; | |
| 757 | |
| 758 // Before we ask for a full repaint, we check if we already have a | |
| 759 // full coverage of the view size in out list of paint_rects | |
| 760 if (CoversArea(paint_rects, view_size)) | |
| 761 break; | |
| 762 needs_full_paint = false; | |
| 763 } | |
| 764 } | |
| 765 } | |
| 766 | |
| 712 if (needs_full_paint) { | 767 if (needs_full_paint) { |
| 713 repaint_start_time_ = TimeTicks::Now(); | 768 repaint_start_time_ = TimeTicks::Now(); |
| 714 repaint_ack_pending_ = true; | 769 repaint_ack_pending_ = true; |
| 715 Send(new ViewMsg_Repaint(routing_id_, view_size)); | 770 Send(new ViewMsg_Repaint(routing_id_, view_size)); |
| 716 } | 771 } |
| 717 } | 772 } |
| 718 | 773 |
| 719 void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, | 774 void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, |
| 720 const gfx::Rect& bitmap_rect, | 775 const gfx::Rect& bitmap_rect, |
| 721 int dx, int dy, | 776 int dx, int dy, |
| 722 const gfx::Rect& clip_rect, | 777 const gfx::Rect& clip_rect, |
| 723 const gfx::Size& view_size) { | 778 const gfx::Size& view_size) { |
| 724 if (is_hidden_) { | 779 if (is_hidden_) { |
| 725 // Don't bother updating the backing store when we're hidden. Just mark it | 780 // Don't bother updating the backing store when we're hidden. Just mark it |
| 726 // as being totally invalid. This will cause a complete repaint when the | 781 // as being totally invalid. This will cause a complete repaint when the |
| 727 // view is restored. | 782 // view is restored. |
| 728 needs_repainting_on_restore_ = true; | 783 needs_repainting_on_restore_ = true; |
| 729 return; | 784 return; |
| 730 } | 785 } |
| 731 | 786 |
| 732 // TODO(darin): do we need to do something else if our backing store is not | 787 // TODO(darin): do we need to do something else if our backing store is not |
| 733 // the same size as the advertised view? maybe we just assume there is a | 788 // the same size as the advertised view? maybe we just assume there is a |
| 734 // full paint on its way? | 789 // full paint on its way? |
| 735 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 790 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
| 736 if (!backing_store || (backing_store->size() != view_size)) | 791 if (!backing_store || (backing_store->size() != view_size)) |
| 737 return; | 792 return; |
| 738 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, | 793 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, |
| 739 dx, dy, clip_rect, view_size); | 794 dx, dy, clip_rect, view_size); |
| 740 } | 795 } |
| OLD | NEW |